Integrate 'sofar' into sized_allocs
[akaros.git] / kern / drivers / dev / proc.c
index 64ac2ab..c6479fc 100644 (file)
@@ -17,8 +17,6 @@
  * rather than excise code that won't work, I'm bracketing it with
  * #if 0 until we know we don't want it
  */
-#include <vfs.h>
-#include <kfs.h>
 #include <slab.h>
 #include <kmalloc.h>
 #include <kref.h>
@@ -74,26 +72,10 @@ enum {
 enum {
        CMclose,
        CMclosefiles,
-       CMfixedpri,
        CMhang,
-       CMkill,
-       CMnohang,
-       CMnoswap,
-       CMpri,
-       CMprivate,
-       CMprofile,
-       CMstart,
-       CMstartstop,
-       CMstartsyscall,
-       CMstop,
-       CMwaitstop,
-       CMwired,
-       CMcore,
-       CMvminit,
-       CMvmstart,
-       CMvmkill,
        CMstraceme,
        CMstraceall,
+       CMstrace_drop,
 };
 
 enum {
@@ -138,29 +120,11 @@ struct dirtab procdir[] = {
 static
 struct cmdtab proccmd[] = {
        {CMclose, "close", 2},
-       {CMclosefiles, "closefiles", 1},
-       {CMfixedpri, "fixedpri", 2},
-       {CMhang, "hang", 1},
-       {CMnohang, "nohang", 1},
-       {CMnoswap, "noswap", 1},
-       {CMkill, "kill", 1},
-       {CMpri, "pri", 2},
-       {CMprivate, "private", 1},
-       {CMprofile, "profile", 1},
-       {CMstart, "start", 1},
-       {CMstartstop, "startstop", 1},
-       {CMstartsyscall, "startsyscall", 1},
-       {CMstop, "stop", 1},
-       {CMwaitstop, "waitstop", 1},
-       {CMwired, "wired", 2},
-       {CMcore, "core", 2},
-       {CMcore, "core", 2},
-       {CMcore, "core", 2},
-       {CMvminit, "vminit", 0},
-       {CMvmstart, "vmstart", 0},
-       {CMvmkill, "vmkill", 0},
+       {CMclosefiles, "closefiles", 0},
+       {CMhang, "hang", 0},
        {CMstraceme, "straceme", 0},
        {CMstraceall, "straceall", 0},
+       {CMstrace_drop, "strace_drop", 2},
 };
 
 /*
@@ -394,12 +358,12 @@ static struct chan *procattach(char *spec)
 }
 
 static struct walkqid *procwalk(struct chan *c, struct chan *nc, char **name,
-                                                               int nname)
+                                                               unsigned int nname)
 {
        return devwalk(c, nc, name, nname, 0, 0, procgen);
 }
 
-static int procstat(struct chan *c, uint8_t * db, int n)
+static size_t procstat(struct chan *c, uint8_t *db, size_t n)
 {
        return devstat(c, db, n, 0, 0, procgen);
 }
@@ -425,9 +389,8 @@ static void nonone(struct proc *p)
 }
 
 struct bm_helper {
-       void                                            *buf;
+       struct sized_alloc                      *sza;
        size_t                                          buflen;
-       size_t                                          sofar;
 };
 
 static void get_needed_sz_cb(struct vm_region *vmr, void *arg)
@@ -441,53 +404,48 @@ static void get_needed_sz_cb(struct vm_region *vmr, void *arg)
 static void build_maps_cb(struct vm_region *vmr, void *arg)
 {
        struct bm_helper *bmh = (struct bm_helper*)arg;
+       struct sized_alloc *sza = bmh->sza;
        size_t old_sofar;
        char path_buf[MAX_FILENAME_SZ];
        char *path;
        unsigned long inode_nr;
 
-       if (vmr->vm_file) {
-               path = file_abs_path(vmr->vm_file, path_buf, sizeof(path_buf));
-               inode_nr = vmr->vm_file->f_dentry->d_inode->i_ino;
+       if (vmr_has_file(vmr)) {
+               path = foc_abs_path(vmr->__vm_foc, path_buf, sizeof(path_buf));
+               inode_nr = 0; /* TODO: do we care about this? */
        } else {
                strlcpy(path_buf, "[heap]", sizeof(path_buf));
                path = path_buf;
                inode_nr = 0;
        }
 
-       old_sofar = bmh->sofar;
-       bmh->sofar += snprintf(bmh->buf + bmh->sofar, bmh->buflen - bmh->sofar,
-                              "%08lx-%08lx %c%c%c%c %08x %02d:%02d %d ",
-                              vmr->vm_base, vmr->vm_end,
-                              vmr->vm_prot & PROT_READ    ? 'r' : '-',
-                              vmr->vm_prot & PROT_WRITE   ? 'w' : '-',
-                              vmr->vm_prot & PROT_EXEC    ? 'x' : '-',
-                              vmr->vm_flags & MAP_PRIVATE ? 'p' : '-',
-                              vmr->vm_file ? vmr->vm_foff : 0,
-                              vmr->vm_file ? 1 : 0,    /* VFS == 1 for major */
-                              0,
-                              inode_nr);
+       old_sofar = sza->sofar;
+       sza_printf(sza, "%08lx-%08lx %c%c%c%c %08x %02d:%02d %d ",
+                       vmr->vm_base, vmr->vm_end,
+                       vmr->vm_prot & PROT_READ    ? 'r' : '-',
+                       vmr->vm_prot & PROT_WRITE   ? 'w' : '-',
+                       vmr->vm_prot & PROT_EXEC    ? 'x' : '-',
+                       vmr->vm_flags & MAP_PRIVATE ? 'p' : 's',
+                       vmr_has_file(vmr) ? vmr->vm_foff : 0,
+                       vmr_has_file(vmr) ? 1 : 0,      /* VFS == 1 for major */
+                       0,
+                       inode_nr);
        /* Align the filename to the 74th char, like Linux (73 chars so far) */
-       bmh->sofar += snprintf(bmh->buf + bmh->sofar, bmh->buflen - bmh->sofar,
-                              "%*s", 73 - (bmh->sofar - old_sofar), "");
-       bmh->sofar += snprintf(bmh->buf + bmh->sofar, bmh->buflen - bmh->sofar,
-                              "%s\n", path);
+       sza_printf(sza, "%*s", 73 - (sza->sofar - old_sofar), "");
+       sza_printf(sza, "%s\n", path);
 }
 
 static struct sized_alloc *build_maps(struct proc *p)
 {
        struct bm_helper bmh[1];
-       struct sized_alloc *sza;
 
        /* Try to figure out the size needed: start with extra space, then add a bit
         * for each VMR */
        bmh->buflen = 150;
        enumerate_vmrs(p, get_needed_sz_cb, bmh);
-       sza = sized_kzmalloc(bmh->buflen, MEM_WAIT);
-       bmh->buf = sza->buf;
-       bmh->sofar = 0;
+       bmh->sza = sized_kzmalloc(bmh->buflen, MEM_WAIT);
        enumerate_vmrs(p, build_maps_cb, bmh);
-       return sza;
+       return bmh->sza;
 }
 
 static struct chan *procopen(struct chan *c, int omode)
@@ -628,6 +586,10 @@ static struct chan *procopen(struct chan *c, int omode)
                                spin_unlock(&p->strace->lock);
                                error(EBUSY, "Process is already being traced");
                        }
+                       /* It's not critical that we reopen before setting tracing, but it's
+                        * a little cleaner (concurrent syscalls could be trying to use the
+                        * queue before it was reopened, and they'd throw). */
+                       qreopen(p->strace->q);
                        p->strace->tracing = TRUE;
                        spin_unlock(&p->strace->lock);
                        /* the ref we are upping is the one we put in __proc_free, which is
@@ -681,7 +643,7 @@ static struct chan *procopen(struct chan *c, int omode)
        return tc;
 }
 
-static int procwstat(struct chan *c, uint8_t * db, int n)
+static size_t procwstat(struct chan *c, uint8_t *db, size_t n)
 {
        ERRSTACK(2);
        error(ENOSYS, ERROR_FIXME);
@@ -723,7 +685,7 @@ static int procwstat(struct chan *c, uint8_t * db, int n)
                else
                        proc_set_username(p, d->uid);
        }
-       if (d->mode != ~0UL)
+       if (d->mode != -1)
                p->procmode = d->mode & 0777;
 
        poperror();
@@ -853,6 +815,7 @@ static void procclose(struct chan *c)
 
                assert(c->flag & COPEN);        /* only way aux should have been set */
                s->tracing = FALSE;
+               qhangup(s->q, NULL);
                kref_put(&s->users);
                c->aux = NULL;
        }
@@ -932,7 +895,7 @@ static int eventsavailable(void *)
 }
 #endif
 
-static long procread(struct chan *c, void *va, long n, int64_t off)
+static size_t procread(struct chan *c, void *va, size_t n, off64_t off)
 {
        ERRSTACK(1);
        struct proc *p;
@@ -1071,7 +1034,7 @@ static long procread(struct chan *c, void *va, long n, int64_t off)
                        return i;
                case Qmaps:
                        sza = c->aux;
-                       i = readmem(off, va, n, sza->buf, sza->size);
+                       i = readstr(off, va, n, sza->buf);
                        proc_decref(p);
                        return i;
        }
@@ -1114,7 +1077,7 @@ static void mntscan(struct mntwalk *mw, struct proc *p)
        runlock(&pg->ns);
 }
 
-static long procwrite(struct chan *c, void *va, long n, int64_t off)
+static size_t procwrite(struct chan *c, void *va, size_t n, off64_t off)
 {
        ERRSTACK(2);
 
@@ -1305,20 +1268,8 @@ void procstopwait(struct proc *p, int ctl)
 static void procctlcloseone(struct proc *p, int fd)
 {
 // TODO: resolve this and sys_close
-       struct file *file = get_file_from_fd(&p->open_files, fd);
-       int retval = 0;
-       printd("%s %d\n", __func__, fd);
-       /* VFS */
-       if (file) {
-               put_file_from_fd(&p->open_files, fd);
-               kref_put(&file->f_kref);        /* Drop the ref from get_file */
-               return;
-       }
-       /* 9ns, should also handle errors (bad FD, etc) */
-       retval = sysclose(fd);
+       sysclose(fd);
        return;
-
-       //sys_close(p, fd);
 }
 
 void procctlclosefiles(struct proc *p, int all, int fd)
@@ -1376,12 +1327,16 @@ static void procctlreq(struct proc *p, char *va, int n)
        switch (ct->index) {
        case CMstraceall:
        case CMstraceme:
+       case CMstrace_drop:
                /* common allocation.  if we inherited, we might have one already */
                if (!p->strace) {
                        strace = kzmalloc(sizeof(*p->strace), MEM_WAIT);
                        spinlock_init(&strace->lock);
                        bitmap_set(strace->trace_set, 0, MAX_SYSCALL_NR);
-                       strace->q = qopen(65536, Qdropoverflow|Qcoalesce, NULL, NULL);
+                       strace->q = qopen(65536, Qmsg, NULL, NULL);
+                       /* The queue is reopened and hungup whenever we open the Qstrace
+                        * file.  This hangup might not be necessary, but is safer. */
+                       qhangup(strace->q, NULL);
                        /* both of these refs are put when the proc is freed.  procs is for
                         * every process that has this p->strace.  users is procs + every
                         * user (e.g. from open()).
@@ -1405,8 +1360,6 @@ static void procctlreq(struct proc *p, char *va, int n)
 
        /* actually do the command. */
        switch (ct->index) {
-       case CMvmstart:
-       case CMvmkill:
        default:
                error(EFAIL, "Command not implemented");
                break;
@@ -1420,28 +1373,20 @@ static void procctlreq(struct proc *p, char *va, int n)
                we may want this.Let us pause a proc.case CMhang:p->hang = 1;
                break;
 #endif
-       case CMkill:
-               p = pid2proc(strtol(cb->f[1], 0, 0));
-               if (!p)
-                       error(EFAIL, "No such proc\n");
-
-               enable_irqsave(&irq_state);
-               proc_destroy(p);
-               disable_irqsave(&irq_state);
-               proc_decref(p);
-               /* this is a little ghetto. it's not fully free yet, but we are also
-                * slowing it down by messing with it, esp with the busy waiting on a
-                * hyperthreaded core. */
-               spin_on(p->env_cr3);
-               break;
-       case CMvminit:
-               break;
        case CMstraceme:
                p->strace->inherit = FALSE;
                break;
        case CMstraceall:
                p->strace->inherit = TRUE;
                break;
+       case CMstrace_drop:
+               if (!strcmp(cb->f[1], "on"))
+                       p->strace->drop_overflow = TRUE;
+               else if (!strcmp(cb->f[1], "off"))
+                       p->strace->drop_overflow = FALSE;
+               else
+                       error(EINVAL, "strace_drop takes on|off %s", cb->f[1]);
+               break;
        }
        poperror();
        kfree(cb);