]> Zhao Yanbai Git Server - minix.git/commitdiff
FS support for grant-based i/o.
authorBen Gras <ben@minix3.org>
Tue, 20 Jun 2006 10:12:09 +0000 (10:12 +0000)
committerBen Gras <ben@minix3.org>
Tue, 20 Jun 2006 10:12:09 +0000 (10:12 +0000)
For character device i/o, FS does a so-called 'magic' grant to let the
driver copy from or to user space. As this is done in FS address space,
the driver is told to do this in FS address space. The redirection to
the right user process then happens at copy-time in the kernel, using the
FS grant table. This also happens for DEV_READ and DEV_WRITE on block
devices.

For other block device i/o, which happens from/to FS buffers, FS does
a 'direct' grant to its own address space for the driver.

After the i/o returns, this access has to be K-I-L-L-E-D, revoked.
Sometimes this is after a SUSPEND and DEV_REVIVE, in which case the
revoking happens in pipe.c.

This conversion happens in safe_io_conversion() in device.c, called
by dev_io and dev_bio.

FS has to pre-allocate its own space for these grant tables. This happens
in main.c.

servers/fs/Makefile
servers/fs/cache.c
servers/fs/device.c
servers/fs/fproc.h
servers/fs/main.c
servers/fs/misc.c
servers/fs/pipe.c
servers/fs/proto.h

index 1e60f7d5f85fd391fbafab0a1ace382c8c02be65..fbd28cd5e8c851a0b30f1aeecf7cbffa719c198a 100644 (file)
@@ -22,7 +22,7 @@ OBJ = main.o open.o read.o write.o pipe.o dmap.o \
 install all build:     $(SERVER)
 $(SERVER):     $(OBJ)
        $(CC) -o $@ $(LDFLAGS) $(OBJ) $(LIBS)
-       install -S 512w $@
+       install -S 1024w $@
 
 # clean up local files
 clean:
index 7189931fa7d8ceb194a06400256f9cd574717c0b..f5e7100b4d4ad6571154e7de7ced097afc5b3f0d 100644 (file)
@@ -70,6 +70,7 @@ int only_search;              /* if NO_READ, don't read, else act normal */
                        /* This block is not the one sought. */
                        bp = bp->b_hash; /* move to next block on hash chain */
                }
+
        }
   }
 
@@ -272,7 +273,7 @@ int rw_flag;                        /* READING or WRITING */
   if ( (dev = bp->b_dev) != NO_DEV) {
        pos = (off_t) bp->b_blocknr * block_size;
        op = (rw_flag == READING ? DEV_READ : DEV_WRITE);
-       r = dev_bio(op, dev, FS_PROC_NR, bp->b_data, pos, block_size, 0);
+       r = dev_bio(op, dev, FS_PROC_NR, bp->b_data, pos, block_size);
        if (r != block_size) {
            if (r >= 0) r = END_OF_FILE;
            if (r != END_OF_FILE)
@@ -376,7 +377,7 @@ int rw_flag;                        /* READING or WRITING */
        }
        r = dev_bio(rw_flag == WRITING ? DEV_SCATTER : DEV_GATHER,
                dev, FS_PROC_NR, iovec,
-               (off_t) bufq[0]->b_blocknr * block_size, j, 0);
+               (off_t) bufq[0]->b_blocknr * block_size, j);
 
        /* Harvest the results.  Dev_io reports the first error it may have
         * encountered, but we only care if it's the first block that failed.
index 9aeb73bab0807ff850520e38c40fb43db9b22bb4..e1d75d7399c3d545d8c0a04d6bb75bc4f71851f8 100644 (file)
 
 #include "fs.h"
 #include <fcntl.h>
+#include <assert.h>
 #include <minix/callnr.h>
 #include <minix/com.h>
 #include <minix/endpoint.h>
+#include <minix/ioctl.h>
 #include "file.h"
 #include "fproc.h"
 #include "inode.h"
 
 #define ELEMENTS(a) (sizeof(a)/sizeof((a)[0]))
 
+FORWARD _PROTOTYPE( int safe_io_conversion, (endpoint_t, int,
+  cp_grant_id_t *, int *, cp_grant_id_t *, int, endpoint_t *,
+  void *, int *, vir_bytes, off_t *));
+FORWARD _PROTOTYPE( void safe_io_cleanup, (cp_grant_id_t, cp_grant_id_t *, int));
+
 extern int dmap_size;
 PRIVATE int dummyproc;
 
@@ -72,12 +79,34 @@ dev_t dev;                  /* device to close */
 }
 
 /*===========================================================================*
- *                             dev_status                                      *
+ *                             suspended_ep                                 *
+ *===========================================================================*/
+endpoint_t suspended_ep(endpoint_t driver, cp_grant_id_t g)
+{
+/* A process is suspended on a driver for which FS issued
+ * a grant. Find out which process it was.
+ */
+       struct fproc *rfp;
+       for (rfp = &fproc[0]; rfp < &fproc[NR_PROCS]; rfp++) {
+               if(rfp->fp_pid == PID_FREE)
+                       continue;
+               if(rfp->fp_suspended == SUSPENDED &&
+                  rfp->fp_task == -driver && rfp->fp_grant == g) {
+                       return rfp->fp_endpoint;
+               }
+       }
+
+       return NONE;
+}
+
+/*===========================================================================*
+ *                             dev_status                                   *
  *===========================================================================*/
 PUBLIC void dev_status(message *m)
 {
        message st;
        int d, get_more = 1;
+       endpoint_t endpt;
 
        for(d = 0; d < NR_DEVICES; d++)
                if (dmap[d].dmap_driver != NONE &&
@@ -100,7 +129,18 @@ PUBLIC void dev_status(message *m)
 
                switch(st.m_type) {
                        case DEV_REVIVE:
-                               revive(st.REP_ENDPT, st.REP_STATUS);
+                               endpt = st.REP_ENDPT;
+                               if(endpt == FS_PROC_NR) {
+                                       endpt = suspended_ep(m->m_source,
+                                               st.REP_IO_GRANT);
+                                       if(endpt == NONE) {
+                                               printf("FS: proc with "
+                                       "grant %d not found (revive)\n",
+                                       st.REP_IO_GRANT);
+                                               continue;
+                                       }
+                               }
+                               revive(endpt, st.REP_STATUS);
                                break;
                        case DEV_IO_READY:
                                select_notified(d, st.DEV_MINOR, st.DEV_SEL_OPS);
@@ -117,21 +157,143 @@ PUBLIC void dev_status(message *m)
        return;
 }
 
+/*===========================================================================*
+ *                             safe_io_conversion                           *
+ *===========================================================================*/
+PRIVATE int safe_io_conversion(driver, dev, gid, op, gids, gids_size,
+       io_ept, buf, vec_grants, bytes, pos)
+endpoint_t driver;
+int dev;
+cp_grant_id_t *gid;
+int *op;
+cp_grant_id_t *gids;
+int gids_size;
+endpoint_t *io_ept;
+void *buf;
+int *vec_grants;
+vir_bytes bytes;
+off_t *pos;
+{
+       int access = 0, size;
+       int m, j;
+       iovec_t *v;
+
+       /* Is this device driver (identified by major number)
+        * ready to accept *_S commands?
+        */
+       if(major(dev) == 7)     /* major number of inet. */
+               return 0;       /* inet is not safe-capable. */
+
+       /* Number of grants allocated in vector I/O. */
+       *vec_grants = 0;
+
+       /* Driver can handle it - change request to a safe one. */
+
+       *gid = GRANT_INVALID;
+
+       switch(*op) {
+               case DEV_READ:
+               case DEV_WRITE:
+                       /* Change to safe op. */
+                       *op = *op == DEV_READ ? DEV_READ_S : DEV_WRITE_S;
+
+                       if((*gid=cpf_grant_magic(driver, *io_ept,
+                         (vir_bytes) buf, bytes,
+                         *op == DEV_READ_S ? CPF_WRITE : CPF_READ)) < 0) {
+                               panic(__FILE__,
+                                "cpf_grant_magic of buffer failed\n", NO_NUM);
+                       }
+
+                       break;
+               case DEV_GATHER:
+               case DEV_SCATTER:
+                       /* Change to safe op. */
+                       *op = *op == DEV_GATHER ? DEV_GATHER_S : DEV_SCATTER_S;
+
+                       /* Grant access to i/o vector. */
+                       if((*gid = cpf_grant_direct(driver, (vir_bytes)
+                         buf, bytes * sizeof(iovec_t),
+                         CPF_READ | CPF_WRITE)) < 0) {
+                               panic(__FILE__,
+                               "cpf_grant_direct of vector failed", NO_NUM);
+                       }
+                       v = (iovec_t *) buf;
+                       /* Grant access to i/o buffers. */
+                       for(j = 0; j < bytes; j++) {
+                          gids[j] = v[j].iov_addr =
+                            cpf_grant_direct(driver, (vir_bytes)
+                            v[j].iov_addr, v[j].iov_size,
+                            *op == DEV_GATHER_S ? CPF_WRITE : CPF_READ);
+                          if(!GRANT_VALID(gids[j])) {
+                               panic(__FILE__, "grant to iovec buf failed",
+                                NO_NUM);
+                          }
+                          (*vec_grants)++;
+                       }
+                       break;
+               case DEV_IOCTL:
+                       *pos = *io_ept; /* Old endpoint in POSITION field. */
+                       *op = DEV_IOCTL_S;
+                       if(_MINIX_IOCTL_IOR(m_in.REQUEST)) access |= CPF_WRITE;
+                       if(_MINIX_IOCTL_IOW(m_in.REQUEST)) access |= CPF_READ;
+                       size = _MINIX_IOCTL_SIZE(m_in.REQUEST);
+                       if(access && size > 0) {
+                               if((*gid=cpf_grant_magic(driver, *io_ept,
+                                       (vir_bytes) buf, size, access)) < 0) {
+                                       panic(__FILE__,
+                                       "cpf_grant_magic failed (ioctl)\n",
+                                       NO_NUM);
+                               }
+                       }
+       }
+
+       /* If we have converted to a safe operation, I/O
+        * endpoint becomes FS if it wasn't already.
+        */
+       if(GRANT_VALID(*gid)) {
+               *io_ept = FS_PROC_NR;
+               return 1;
+       }
+
+       /* Not converted to a safe operation (because there is no
+        * copying involved in this operation).
+        */
+       return 0;
+}
+
+/*===========================================================================*
+ *                     safe_io_cleanup                                      *
+ *===========================================================================*/
+PRIVATE void safe_io_cleanup(gid, gids, gids_size)
+cp_grant_id_t gid;
+cp_grant_id_t *gids;
+int gids_size;
+{
+/* Free resources (specifically, grants) allocated by safe_io_conversion(). */
+       int j;
+
+       cpf_revoke(gid);
+
+       for(j = 0; j < gids_size; j++)
+               cpf_revoke(gids[j]);
+
+       return;
+}
+
 /*===========================================================================*
  *                             dev_bio                                      *
  *===========================================================================*/
-PUBLIC int dev_bio(op, dev, proc_e, buf, pos, bytes, flags)
+PUBLIC int dev_bio(op, dev, proc_e, buf, pos, bytes)
 int op;                                /* DEV_READ, DEV_WRITE, DEV_IOCTL, etc. */
 dev_t dev;                     /* major-minor device number */
 int proc_e;                    /* in whose address space is buf? */
 void *buf;                     /* virtual address of the buffer */
 off_t pos;                     /* byte position */
 int bytes;                     /* how many bytes to transfer */
-int flags;                     /* special flags, like O_NONBLOCK */
 {
 /* Read or write from a device.  The parameter 'dev' tells which one. */
   struct dmap *dp;
-  int r;
+  int r, safe;
   message m;
 
   /* Determine task dmap. */
@@ -139,24 +301,40 @@ int flags;                        /* special flags, like O_NONBLOCK */
 
   for (;;)
   {
+        static cp_grant_id_t gids[NR_IOREQS];
+        cp_grant_id_t gid = GRANT_INVALID;
+       int vec_grants;
+
        /* See if driver is roughly valid. */
        if (dp->dmap_driver == NONE) {
                printf("FS: dev_io: no driver for dev %x\n", dev);
                return ENXIO;
        }
 
-       /* Set up the message passed to task. */
+        /* By default, these are right. */
+        m.IO_ENDPT = proc_e;
+        m.ADDRESS  = buf;
+
+       /* Convert parameters to 'safe mode'. */
+        safe = safe_io_conversion(dp->dmap_driver, dev, &gid,
+          &op, gids, NR_IOREQS, &m.IO_ENDPT, buf, &vec_grants, bytes, &pos);
+
+       /* Set up rest of the message. */
+       if(safe) m.IO_GRANT = (char *) gid;
        m.m_type   = op;
        m.DEVICE   = (dev >> MINOR) & BYTE;
        m.POSITION = pos;
-       m.IO_ENDPT = proc_e;
-       m.ADDRESS  = buf;
        m.COUNT    = bytes;
-       m.TTY_FLAGS = flags;
+       m.HIGHPOS  = 0;
 
        /* Call the task. */
        (*dp->dmap_io)(dp->dmap_driver, &m);
 
+       /* As block I/O never SUSPENDs, safe cleanup must be done whether
+        * the I/O succeeded or not.
+        */
+       if(safe) safe_io_cleanup(gid, gids, vec_grants);
+
        if(dp->dmap_driver == NONE) {
                /* Driver has vanished. Wait for a new one. */
                for (;;)
@@ -217,9 +395,13 @@ int flags;                 /* special flags, like O_NONBLOCK */
 /* Read or write from a device.  The parameter 'dev' tells which one. */
   struct dmap *dp;
   message dev_mess;
+  cp_grant_id_t gid = GRANT_INVALID;
+  static cp_grant_id_t gids[NR_IOREQS];
+  int vec_grants = 0, orig_op, safe;
 
   /* Determine task dmap. */
   dp = &dmap[(dev >> MAJOR) & BYTE];
+  orig_op = op;
 
   /* See if driver is roughly valid. */
   if (dp->dmap_driver == NONE) {
@@ -233,38 +415,71 @@ int flags;                        /* special flags, like O_NONBLOCK */
        return ENXIO;
   }
 
-  /* Set up the message passed to task. */
+  /* By default, these are right. */
+  dev_mess.IO_ENDPT = proc_e;
+  dev_mess.ADDRESS  = buf;
+
+  /* Convert DEV_* to DEV_*_S variants. */
+  safe = safe_io_conversion(dp->dmap_driver, dev, &gid,
+    &op, gids, NR_IOREQS, &dev_mess.IO_ENDPT, buf, &vec_grants, bytes, &pos);
+
+  /* If the safe conversion was done, set the ADDRESS to
+   * the grant id.
+   */
+  if(safe) dev_mess.IO_GRANT = (char *) gid;
+
+  /* Set up the rest of the message passed to task. */
   dev_mess.m_type   = op;
   dev_mess.DEVICE   = (dev >> MINOR) & BYTE;
   dev_mess.POSITION = pos;
-  dev_mess.IO_ENDPT = proc_e;
-  dev_mess.ADDRESS  = buf;
   dev_mess.COUNT    = bytes;
-  dev_mess.TTY_FLAGS = flags;
+  dev_mess.HIGHPOS  = 0;
+
+  /* This field will be used if the i/o is suspended. */
+  fp->fp_ioproc = dev_mess.IO_ENDPT;
 
   /* Call the task. */
   (*dp->dmap_io)(dp->dmap_driver, &dev_mess);
 
   if(dp->dmap_driver == NONE) {
        /* Driver has vanished. */
+       printf("Driver gone?\n");
+       if(safe) safe_io_cleanup(gid, gids, vec_grants);
        return EIO;
   }
 
   /* Task has completed.  See if call completed. */
   if (dev_mess.REP_STATUS == SUSPEND) {
+       if(vec_grants > 0) {
+               panic(__FILE__,"SUSPEND on vectored i/o", NO_NUM);
+       }
        if (flags & O_NONBLOCK) {
                /* Not supposed to block. */
                dev_mess.m_type = CANCEL;
-               dev_mess.IO_ENDPT = proc_e;
+               dev_mess.IO_ENDPT = fp->fp_ioproc;
+               dev_mess.IO_GRANT = (char *) gid;
+
+               /* This R_BIT/W_BIT check taken from suspend()/unpause()
+                * logic. Mode is expected in the COUNT field.
+                */
+               dev_mess.COUNT = 0;
+               if(call_nr == READ)             dev_mess.COUNT = R_BIT;
+               else if(call_nr == WRITE)       dev_mess.COUNT = W_BIT;
                dev_mess.DEVICE = (dev >> MINOR) & BYTE;
                (*dp->dmap_io)(dp->dmap_driver, &dev_mess);
                if (dev_mess.REP_STATUS == EINTR) dev_mess.REP_STATUS = EAGAIN;
        } else {
                /* Suspend user. */
                suspend(dp->dmap_driver);
+               assert(!GRANT_VALID(fp->fp_grant));
+               fp->fp_grant = gid;     /* revoke this when unsuspended. */
                return(SUSPEND);
        }
   }
+
+  /* No suspend, or cancelled suspend, so I/O is over and can be cleaned up. */
+  if(safe) safe_io_cleanup(gid, gids, vec_grants);
+
   return(dev_mess.REP_STATUS);
 }
 
@@ -389,40 +604,6 @@ PUBLIC int do_ioctl()
        && (rip->i_mode & I_TYPE) != I_BLOCK_SPECIAL) return(ENOTTY);
   dev = (dev_t) rip->i_zone[0];
 
-#if ENABLE_BINCOMPAT
-  if ((m_in.TTY_REQUEST >> 8) == 't') {
-       /* Obsolete sgtty ioctl, message contains more than is sane. */
-       struct dmap *dp;
-       message dev_mess;
-
-       dp = &dmap[(dev >> MAJOR) & BYTE];
-
-       dev_mess = m;   /* Copy full message with all the weird bits. */
-       dev_mess.m_type   = DEV_IOCTL;
-       dev_mess.PROC_NR  = who_e;
-       dev_mess.TTY_LINE = (dev >> MINOR) & BYTE;      
-
-       /* Call the task. */
-
-  if (dp->dmap_driver == NONE) {
-       printf("FS: do_ioctl: no driver for dev %x\n", dev);
-       return ENXIO;
-  }
-
-  if(isokendpt(dp->dmap_driver, &dummyproc) != OK) {
-       printf("FS: do_ioctl: old driver for dev %x (%d)\n",
-               dev, dp->dmap_driver);
-       return ENXIO;
-  }
-
-       (*dp->dmap_io)(dp->dmap_driver, &dev_mess);
-
-       m_out.TTY_SPEK = dev_mess.TTY_SPEK;     /* erase and kill */
-       m_out.TTY_FLAGS = dev_mess.TTY_FLAGS;   /* flags */
-       return(dev_mess.REP_STATUS);
-  }
-#endif
-
   return(dev_io(DEV_IOCTL, dev, who_e, m_in.ADDRESS, 0L, 
        m_in.REQUEST, f->filp_flags));
 }
@@ -494,10 +675,14 @@ message *mess_ptr;                /* pointer to message for task */
        /* Did the process we did the sendrec() for get a result? */
        if (mess_ptr->REP_ENDPT == proc_e) {
                break;
-       } else if (mess_ptr->m_type == REVIVE) {
+       } 
+#if 0
+       else if (mess_ptr->m_type == REVIVE) {
                /* Otherwise it should be a REVIVE. */
                revive(mess_ptr->REP_ENDPT, mess_ptr->REP_STATUS);
-       } else {
+       }
+#endif
+       else {
                printf(
                "fs: strange device reply from %d, type = %d, proc = %d (2) ignored\n",
                        mess_ptr->m_source,
index a9889094f6b496b48621db6c4a7aa47c97bc48ef..98c0d90c98815c53355a71ad58dd2590782a0f16 100644 (file)
@@ -1,4 +1,5 @@
 #include <sys/select.h>
+#include <minix/safecopies.h>
 
 /* This is the per-process information.  A slot is reserved for each potential
  * process. Thus NR_PROCS must be the same as in the kernel. It is not 
@@ -22,11 +23,13 @@ EXTERN struct fproc {
   char fp_suspended;           /* set to indicate process hanging */
   char fp_revived;             /* set to indicate process being revived */
   int fp_task;                 /* which task is proc suspended on */
+  endpoint_t fp_ioproc;                /* proc no. in suspended-on i/o message */
+  cp_grant_id_t fp_grant;      /* revoke this grant on unsuspend if > -1 */
   char fp_sesldr;              /* true if proc is a session leader */
   char fp_execced;             /* true if proc has exec()ced after fork */
   pid_t fp_pid;                        /* process id */
   long fp_cloexec;             /* bit map for POSIX Table 6-2 FD_CLOEXEC */
-  int fp_endpoint;             /* kernel endpoint number of this process */
+  endpoint_t fp_endpoint;      /* kernel endpoint number of this process */
 } fproc[NR_PROCS];
 
 /* Field values. */
index 6335803ae098cd1ecfc0b967d4a6a8ee8e099656..7aa62badfa26741b59dad16812d300931cc16a2b 100644 (file)
@@ -15,6 +15,7 @@ struct super_block;           /* proto.h needs to know this */
 #include <string.h>
 #include <stdio.h>
 #include <signal.h>
+#include <assert.h>
 #include <stdlib.h>
 #include <sys/ioc_memory.h>
 #include <sys/svrctl.h>
@@ -24,6 +25,7 @@ struct super_block;           /* proto.h needs to know this */
 #include <minix/keymap.h>
 #include <minix/const.h>
 #include <minix/endpoint.h>
+#include <minix/safecopies.h>
 #include "buf.h"
 #include "file.h"
 #include "fproc.h"
@@ -136,6 +138,10 @@ PRIVATE void get_work()
                        rp->fp_suspended = NOT_SUSPENDED; /*no longer hanging*/
                        rp->fp_revived = NOT_REVIVING;
                        reviving--;
+                       /* This should be a pipe I/O, not a device I/O.
+                        * If it is, it'll 'leak' grants.
+                        */
+                       assert(!GRANT_VALID(rp->fp_grant));
                        return;
                }
        panic(__FILE__,"get_work couldn't revive anyone", NO_NUM);
@@ -219,6 +225,22 @@ PRIVATE void fs_init()
   message mess;
   int s;
 
+/* Maximum number of outstanding grants is one full i/o
+ * vector, and all processes hanging on SUSPENDed i/o, and
+ * grants for printf() to tty and log.
+ *
+ * Space is declared for it here, and cpf_preallocate()
+ * uses it internally and internally tells the kernel
+ * about it. FS then never touches the data again directly,
+ * only through the cpf_* library routines.
+ */
+#define NGRANTS (NR_PROCS + NR_IOREQS + 10)
+  static cp_grant_t grants[NGRANTS];
+
+  /* Set data copy grant table, as FS can't allocate it dynamically. */
+  if(cpf_preallocate(grants, NGRANTS) != OK)
+       panic(__FILE__,"cpf_preallocate failed", NO_NUM);
+
   /* Initialize the process table with help of the process manager messages. 
    * Expect one message for each system process with its slot number and pid. 
    * When no more processes follow, the magic process number NONE is sent. 
@@ -237,6 +259,7 @@ PRIVATE void fs_init()
        rfp->fp_realgid = (gid_t) SYS_GID;
        rfp->fp_effgid = (gid_t) SYS_GID;
        rfp->fp_umask = ~0;
+       rfp->fp_grant = GRANT_INVALID;
    
   } while (TRUE);                      /* continue until process NONE */
   mess.m_type = OK;                    /* tell PM that we succeeded */
@@ -334,8 +357,9 @@ PRIVATE void service_pm()
                {
                        panic("fs", "service_pm: sendrec failed", r);
                }
-               if (m.m_type == PM_IDLE)
+               if (m.m_type == PM_IDLE) {
                        break;
+               }
                call= m.m_type;
                switch(call)
                {
index cfb8505756b8d0643a7dfc78ff36b311210d1c79..93f59288efb47119b4c5ec02ddc4c98d8b9e13f7 100644 (file)
 
 #include "fs.h"
 #include <fcntl.h>
+#include <assert.h>
 #include <unistd.h>    /* cc runs out of memory with unistd.h :-( */
 #include <minix/callnr.h>
+#include <minix/safecopies.h>
 #include <minix/endpoint.h>
 #include <minix/com.h>
 #include <sys/ptrace.h>
@@ -351,6 +353,12 @@ int cpid;  /* Child process id */
   cp->fp_pid = cpid;
   cp->fp_endpoint = cproc;
 
+  /* A forking process never has an outstanding grant,
+   * as it isn't blocking on i/o.
+   */
+  assert(!GRANT_VALID(fp->fp_grant));
+  assert(!GRANT_VALID(cp->fp_grant));
+
   /* A child is not a process leader. */
   cp->fp_sesldr = 0;
 
@@ -661,8 +669,9 @@ struct mem_map *seg_ptr;
                r= sys_trace(T_GETUSER, proc_e, trace_off, &trace_data);
                if  (r != OK) 
                {
-                       printf("dumpcore: sys_trace failed at offset %d: %d\n",
-                               trace_off, r);
+                       printf("dumpcore pid %d: sys_trace failed "
+                               "at offset %d: %d\n",
+                               rfp->fp_pid, trace_off, r);
                        break;
                }
                r= write_bytes(rip, off, (char *)&trace_data,
index cea63266668489e7d1fd9a28deca1e648d9368e0..337259318a6e9a7c4c0aec8706d525c817d3f59c 100644 (file)
@@ -18,6 +18,7 @@
 #include "fs.h"
 #include <fcntl.h>
 #include <signal.h>
+#include <assert.h>
 #include <minix/callnr.h>
 #include <minix/endpoint.h>
 #include <minix/com.h>
@@ -192,6 +193,7 @@ int task;                   /* who is proc waiting for? (PIPE = pipe) */
 
   if (task == XPIPE || task == XPOPEN) susp_count++;/* #procs susp'ed on pipe*/
   fp->fp_suspended = SUSPENDED;
+  assert(!GRANT_VALID(fp->fp_grant));
   fp->fp_fd = m_in.fd << 8 | call_nr;
   if(task == NONE)
        panic(__FILE__,"suspend on NONE",NO_NUM);
@@ -316,8 +318,20 @@ int returned;                      /* if hanging on task, how many bytes read */
        else if (task == XSELECT) {
                reply(proc_nr_e, returned);
        } else {
-               /* Revive a process suspended on TTY or other device. */
-               rfp->fp_nbytes = returned;      /*pretend it wants only what there is*/
+               /* Revive a process suspended on TTY or other device. 
+                * Pretend it wants only what there is.
+                */
+               rfp->fp_nbytes = returned; 
+               /* If a grant has been issued by FS for this I/O, revoke
+                * it again now that I/O is done.
+                */
+               if(GRANT_VALID(rfp->fp_grant)) {
+                       if(cpf_revoke(rfp->fp_grant)) {
+                               panic(__FILE__,"FS: revoke failed for grant",
+                                       rfp->fp_grant);
+                       } 
+                       rfp->fp_grant = GRANT_INVALID;
+               }
                reply(proc_nr_e, returned);     /* unblock the process */
        }
   }
@@ -386,13 +400,21 @@ int proc_nr_e;
                f = rfp->fp_filp[fild];
                dev = (dev_t) f->filp_ino->i_zone[0];   /* device hung on */
                mess.TTY_LINE = (dev >> MINOR) & BYTE;
-               mess.IO_ENDPT = proc_nr_e;
+               mess.IO_ENDPT = rfp->fp_ioproc;
+               mess.IO_GRANT = (char *) rfp->fp_grant;
 
                /* Tell kernel R or W. Mode is from current call, not open. */
                mess.COUNT = (rfp->fp_fd & BYTE) == READ ? R_BIT : W_BIT;
                mess.m_type = CANCEL;
                fp = rfp;       /* hack - ctty_io uses fp */
                (*dmap[(dev >> MAJOR) & BYTE].dmap_io)(task, &mess);
+               if(GRANT_VALID(rfp->fp_grant)) {
+                       if(cpf_revoke(rfp->fp_grant)) {
+                               panic(__FILE__,"FS: revoke failed for grant (cancel)",
+                                       rfp->fp_grant);
+                       } 
+                       rfp->fp_grant = GRANT_INVALID;
+               }
   }
 
   rfp->fp_suspended = NOT_SUSPENDED;
index e09412b73f82b82e0b78db6296bf95493bf34b0c..c37d668433619ebe3de4717de48a803f05cb2e85 100644 (file)
@@ -2,6 +2,8 @@
 
 #include "timers.h"
 
+#include <minix/safecopies.h>
+
 /* Structs used in prototypes must be declared as such first. */
 struct buf;
 struct filp;           
@@ -31,7 +33,7 @@ _PROTOTYPE( void invalidate2, (Dev_t device)                          );
 _PROTOTYPE( int dev_open, (Dev_t dev, int proc, int flags)             );
 _PROTOTYPE( void dev_close, (Dev_t dev)                                        );
 _PROTOTYPE( int dev_bio, (int op, Dev_t dev, int proc, void *buf,
-                       off_t pos, int bytes, int flags)                );
+                       off_t pos, int bytes)                           );
 _PROTOTYPE( int dev_io, (int op, Dev_t dev, int proc, void *buf,
                        off_t pos, int bytes, int flags)                );
 _PROTOTYPE( int gen_opcl, (int op, Dev_t dev, int proc, int flags)     );