]> Zhao Yanbai Git Server - minix.git/commitdiff
make vfs & filesystems use failable copying
authorBen Gras <ben@minix3.org>
Thu, 16 Jan 2014 13:22:13 +0000 (14:22 +0100)
committerLionel Sambuc <lionel@minix3.org>
Mon, 28 Jul 2014 15:05:14 +0000 (17:05 +0200)
Change the kernel to add features to vircopy and safecopies so that
transparent copy fixing won't happen to avoid deadlocks, and such copies
fail with EFAULT.

Transparently making copying work from filesystems (as normally done by
the kernel & VM when copying fails because of missing/readonly memory)
is problematic as it can happen that, for file-mapped ranges, that that
same filesystem that is blocked on the copy request is needed to satisfy
the memory range, leading to deadlock. Dito for VFS itself, if done with
a blocking call.

This change makes the copying done from a filesystem fail in such cases
with EFAULT by VFS adding the CPF_TRY flag to the grants. If a FS call
fails with EFAULT, VFS will then request the range to be made available
to VM after the FS is unblocked, allowing it to be used to satisfy the
range if need be in another VFS thread.

Similarly, for datacopies that VFS itself does, it uses the failable
vircopy variant and callers use a wrapper that talk to VM if necessary
to get the copy to work.

. kernel: add CPF_TRY flag to safecopies
. kernel: only request writable ranges to VM for the
  target buffer when copying fails
. do copying in VFS TRY-first
. some fixes in VM to build SANITYCHECK mode
. add regression test for the cases where
  - a FS system call needs memory mapped in a process that the
    FS itself must map.
  - such a range covers more than one file-mapped region.
. add 'try' mode to vircopy, physcopy
. add flags field to copy kernel call messages
. if CP_FLAG_TRY is set, do not transparently try
  to fix memory ranges
. for use by VFS when accessing user buffers to avoid
  deadlock
. remove some obsolete backwards compatability assignments
        . VFS: let thread scheduling work for VM requests too
          Allows VFS to make calls to VM while suspending and resuming
          the currently running thread. Does currently not work for the
          main thread.
        . VM: add fix memory range call for use by VFS

Change-Id: I295794269cea51a3163519a9cfe5901301d90b32

58 files changed:
include/minix/com.h
include/minix/const.h
include/minix/safecopies.h
include/minix/syslib.h
include/minix/vm.h
kernel/arch/earm/memory.c
kernel/arch/i386/do_sdevio.c
kernel/arch/i386/memory.c
kernel/proto.h
kernel/system/do_copy.c
kernel/system/do_safecopy.c
kernel/system/do_safememset.c
kernel/system/do_umap_remote.c
kernel/system/do_vumap.c
lib/libexec/exec_general.c
lib/libsys/safecopies.c
lib/libsys/sys_physcopy.c
lib/libsys/sys_safecopy.c
lib/libsys/sys_vircopy.c
lib/libsys/vm_procctl.c
servers/pm/misc.c
servers/pm/trace.c
servers/rs/exec.c
servers/rs/request.c
servers/vfs/comm.c
servers/vfs/coredump.c
servers/vfs/dmap.c
servers/vfs/exec.c
servers/vfs/lock.c
servers/vfs/main.c
servers/vfs/misc.c
servers/vfs/mount.c
servers/vfs/proto.h
servers/vfs/request.c
servers/vfs/select.c
servers/vfs/stadir.c
servers/vfs/threads.h
servers/vfs/utility.c
servers/vfs/vnode.c
servers/vfs/worker.c
servers/vm/alloc.c
servers/vm/exit.c
servers/vm/fork.c
servers/vm/glo.h
servers/vm/main.c
servers/vm/mem_anon.c
servers/vm/mem_anon_contig.c
servers/vm/mem_cache.c
servers/vm/mem_file.c
servers/vm/mem_shared.c
servers/vm/memtype.h
servers/vm/pagefaults.c
servers/vm/pagetable.c
servers/vm/proto.h
servers/vm/region.c
servers/vm/sanitycheck.h
servers/vm/slaballoc.c
servers/vm/utility.c

index 219345c0aa94fa3c18d353163cc67f83a457cb6e..6377c68457df2f38c746797e351a1ca6049ddfbc 100644 (file)
 #define CP_DST_ENDPT   m5_i2   /* process to copy to */
 #define CP_DST_ADDR    m5_l2   /* address where data go to */
 #define CP_NR_BYTES    m5_l3   /* number of bytes to copy */
+#define CP_FLAGS       m5_s2   /* number of bytes to copy */
 
-#define UMAP_SEG       m5_s1
+#define CP_FLAG_TRY    0x01    /* do not transparently map */
 
-/* only used for backwards compatability */
-#define CP_SRC_SPACE_OBSOLETE  m5_s1   /* T or D space (stack is also D) */
-#define CP_DST_SPACE_OBSOLETE  m5_s2   /* T or D space (stack is also D) */
+#define UMAP_SEG       m5_s1
 
 /* Field names for SYS_VUMAP. */
 #define VUMAP_ENDPT    m10_i1  /* grant owner, or SELF for local addresses */
 
 /* Field names for SYS_SAFECOPY* */
 #define SCP_FROM_TO    m2_i1   /* from/to whom? */
-#define SCP_SEG_OBSOLETE m2_i2 /* my own segment */
 #define SCP_GID                m2_i3   /* grant id */
 #define SCP_OFFSET     m2_l1   /* offset within grant */
 #define SCP_ADDRESS    m2_p1   /* my own address */
 #define VSCP_VEC_ADDR  m2_p1   /* start of vector */
 #define VSCP_VEC_SIZE  m2_l2   /* elements in vector */
 
-#define SMAP_SEG_OBSOLETE      m2_p1
-
 /* Field names for SYS_SPROF, _CPROF, _PROFBUF. */
 #define PROF_ACTION    m7_i1    /* start/stop/reset/get */
 #define PROF_MEM_SIZE  m7_i2    /* available memory for data */ 
 /* same args as VM_REMAP */
 
 #define VM_PROCCTL             (VM_RQ_BASE+45)
-#define VMPCTL_PARAM           m1_i1
-#define VMPCTL_WHO             m1_i2
+#define VMPCTL_PARAM           m9_l1
+#define VMPCTL_WHO             m9_l2
+#define VMPCTL_M1              m9_l3
+#define VMPCTL_LEN             m9_l4
+#define VMPCTL_FLAGS           m9_l5
 
 #define VMPPARAM_CLEAR         1       /* values for VMPCTL_PARAM */
+#define VMPPARAM_HANDLEMEM     2
 
 #define VM_VFS_MMAP             (VM_RQ_BASE+46)
 
index f6da60b864ee7af7db9994c5ca19c8bb6d562f5a..5131e9a00f4437a050e8982d6b697f3180dc40b7 100644 (file)
@@ -53,8 +53,6 @@
 #define SEGMENT_TYPE  0xFF00   /* bit mask to get segment type */
 #define SEGMENT_INDEX 0x00FF   /* bit mask to get segment index */
 
-#define D_OBSOLETE         1   /* proc[i].mem_map[D] is for data */
-
 #define PHYS_SEG      0x0400   /* flag indicating entire physical memory */
 
 #define LOCAL_VM_SEG  0x1000   /* same as LOCAL_SEG, but with vm lookup */
index aa35fc502b51d6f214818a9d4480605fb8d88675..4d9b4e2e84cefddff8d7f120ae4afbbed1d657ac 100644 (file)
@@ -56,6 +56,9 @@ struct vscp_vec {
 #define CPF_READ       0x000001 /* Granted process may read. */
 #define CPF_WRITE      0x000002 /* Granted process may write. */
 
+/* Grant flags. */
+#define CPF_TRY                0x000010 /* Fail fast on unmapped memory. */
+
 /* Internal flags. */
 #define CPF_USED       0x000100 /* Grant slot in use. */
 #define CPF_DIRECT     0x000200 /* Grant from this process to another. */
index f2c0040515e6c0915fb0eb4a2dda78bdd97c098e..834e0ee650ecf4e018b53b164c8c5654f745f28e 100644 (file)
@@ -123,14 +123,15 @@ int sys_vtimer(endpoint_t proc_nr, int which, clock_t *newval, clock_t
 int sys_irqctl(int request, int irq_vec, int policy, int *irq_hook_id);
 
 /* Shorthands for sys_vircopy() and sys_physcopy() system calls. */
-#define sys_datacopy sys_vircopy
+#define sys_datacopy(p1, v1, p2, v2, len) sys_vircopy(p1, v1, p2, v2, len, 0)
+#define sys_datacopy_try(p1, v1, p2, v2, len) sys_vircopy(p1, v1, p2, v2, len, CP_FLAG_TRY)
 int sys_vircopy(endpoint_t src_proc, vir_bytes src_v,
-       endpoint_t dst_proc, vir_bytes dst_vir, phys_bytes bytes);
+       endpoint_t dst_proc, vir_bytes dst_vir, phys_bytes bytes, int flags);
 
 #define sys_abscopy(src_phys, dst_phys, bytes) \
-       sys_physcopy(NONE, src_phys, NONE, dst_phys, bytes)
+       sys_physcopy(NONE, src_phys, NONE, dst_phys, bytes, 0)
 int sys_physcopy(endpoint_t src_proc, vir_bytes src_vir,
-       endpoint_t dst_proc, vir_bytes dst_vir, phys_bytes bytes);
+       endpoint_t dst_proc, vir_bytes dst_vir, phys_bytes bytes, int flags);
 
 
 /* Grant-based copy functions. */
index f748aade4d5108577805ba783d762d873a26ef0b..6dd94cb0fee212d1596c3e54e5512af95ec4f542 100644 (file)
@@ -67,7 +67,8 @@ int vm_info_stats(struct vm_stats_info *vfi);
 int vm_info_usage(endpoint_t who, struct vm_usage_info *vui);
 int vm_info_region(endpoint_t who, struct vm_region_info *vri, int
        count, vir_bytes *next);
-int vm_procctl(endpoint_t ep, int param);
+int vm_procctl_clear(endpoint_t ep);
+int vm_procctl_handlemem(endpoint_t ep, vir_bytes m1, vir_bytes m2, int wr);
 
 int vm_set_cacheblock(void *block, dev_t dev, off_t dev_offset,
         ino_t ino, off_t ino_offset, u32_t *flags, int blocksize);
index ee77a71b8fb3119615c4cfd97db768c496942d59..e8648897c6391e123997bf4cd1e826abbbcac2d7 100644 (file)
@@ -398,7 +398,8 @@ size_t vm_lookup_range(const struct proc *proc, vir_bytes vir_addr,
  *                              vm_suspend                                *
  *===========================================================================*/
 static void vm_suspend(struct proc *caller, const struct proc *target,
-       const vir_bytes linaddr, const vir_bytes len, const int type)
+       const vir_bytes linaddr, const vir_bytes len, const int type,
+       const int writeflag)
 {
        /* This range is not OK for this process. Set parameters  
         * of the request and notify VM about the pending request. 
@@ -412,7 +413,7 @@ static void vm_suspend(struct proc *caller, const struct proc *target,
        caller->p_vmrequest.target = target->p_endpoint;
        caller->p_vmrequest.params.check.start = linaddr;
        caller->p_vmrequest.params.check.length = len;
-       caller->p_vmrequest.params.check.writeflag = 1;
+       caller->p_vmrequest.params.check.writeflag = writeflag;
        caller->p_vmrequest.type = type;
                                                        
        /* Connect caller on vmrequest wait queue. */   
@@ -426,7 +427,7 @@ static void vm_suspend(struct proc *caller, const struct proc *target,
  *                             vm_check_range                               *
  *===========================================================================*/
 int vm_check_range(struct proc *caller, struct proc *target,
-       vir_bytes vir_addr, size_t bytes)
+       vir_bytes vir_addr, size_t bytes, int writeflag)
 {
        /* Public interface to vm_suspend(), for use by kernel calls. On behalf
         * of 'caller', call into VM to check linear virtual address range of
@@ -442,7 +443,8 @@ int vm_check_range(struct proc *caller, struct proc *target,
                        (r = caller->p_vmrequest.vmresult) != OK)
                return r;
 
-       vm_suspend(caller, target, vir_addr, bytes, VMSTYPE_KERNELCALL);
+       vm_suspend(caller, target, vir_addr, bytes, VMSTYPE_KERNELCALL,
+               writeflag);
 
        return VMSUSPEND;
 }
@@ -520,7 +522,7 @@ int vm_memset(struct proc* caller, endpoint_t who, phys_bytes ph, int c,
                        /* If a process pagefaults, VM may help out */
                        if (whoptr) {
                                vm_suspend(caller, whoptr, ph, count,
-                                                  VMSTYPE_KERNELCALL);
+                                                  VMSTYPE_KERNELCALL, 1);
                                assert(catch_pagefaults);
                                catch_pagefaults = 0;
                                return VMSUSPEND;
@@ -589,6 +591,7 @@ int vmcheck;                        /* if nonzero, can return VMSUSPEND */
 
   if((r=lin_lin_copy(procs[_SRC_], vir_addr[_SRC_]->offset,
        procs[_DST_], vir_addr[_DST_]->offset, bytes)) != OK) {
+       int writeflag;
        struct proc *target = NULL;
        phys_bytes lin;
        if(r != EFAULT_SRC && r != EFAULT_DST)
@@ -600,9 +603,11 @@ int vmcheck;                       /* if nonzero, can return VMSUSPEND */
        if(r == EFAULT_SRC) {
                lin = vir_addr[_SRC_]->offset;
                target = procs[_SRC_];
+               writeflag = 0;
        } else if(r == EFAULT_DST) {
                lin = vir_addr[_DST_]->offset;
                target = procs[_DST_];
+               writeflag = 1;
        } else {
                panic("r strange: %d",  r);
        }
@@ -610,7 +615,7 @@ int vmcheck;                        /* if nonzero, can return VMSUSPEND */
        assert(caller);
        assert(target);
 
-       vm_suspend(caller, target, lin, bytes, VMSTYPE_KERNELCALL);
+       vm_suspend(caller, target, lin, bytes, VMSTYPE_KERNELCALL, writeflag);
        return VMSUSPEND;
   }
 
index 23ea4fa240a926a3f73830fb91e5f34a234d2644..4e5a5924c4f3df6197022b5f58edf8106002df46 100644 (file)
@@ -72,7 +72,7 @@ int do_sdevio(struct proc * caller, message *m_ptr)
        count,
        req_dir == _DIO_INPUT ? CPF_WRITE : CPF_READ,
        (vir_bytes) m_ptr->DIO_OFFSET, 
-       &newoffset, &newep) != OK) {
+       &newoffset, &newep, NULL) != OK) {
        printf("do_sdevio: verify_grant failed\n");
        return EPERM;
     }
index 24b866f0b603df8d3d79a69a6851bba631ad3e62..320dbe12f6c34c6318055fb74aaeeeb37f9d239b 100644 (file)
@@ -421,7 +421,8 @@ size_t vm_lookup_range(const struct proc *proc, vir_bytes vir_addr,
  *                              vm_suspend                                *
  *===========================================================================*/
 static void vm_suspend(struct proc *caller, const struct proc *target,
-       const vir_bytes linaddr, const vir_bytes len, const int type)
+       const vir_bytes linaddr, const vir_bytes len, const int type,
+       const int writeflag)
 {
        /* This range is not OK for this process. Set parameters  
         * of the request and notify VM about the pending request. 
@@ -437,7 +438,7 @@ static void vm_suspend(struct proc *caller, const struct proc *target,
        caller->p_vmrequest.target = target->p_endpoint;
        caller->p_vmrequest.params.check.start = linaddr;
        caller->p_vmrequest.params.check.length = len;
-       caller->p_vmrequest.params.check.writeflag = 1;
+       caller->p_vmrequest.params.check.writeflag = writeflag;
        caller->p_vmrequest.type = type;
                                                        
        /* Connect caller on vmrequest wait queue. */   
@@ -451,7 +452,7 @@ static void vm_suspend(struct proc *caller, const struct proc *target,
  *                             vm_check_range                               *
  *===========================================================================*/
 int vm_check_range(struct proc *caller, struct proc *target,
-       vir_bytes vir_addr, size_t bytes)
+       vir_bytes vir_addr, size_t bytes, int writeflag)
 {
        /* Public interface to vm_suspend(), for use by kernel calls. On behalf
         * of 'caller', call into VM to check linear virtual address range of
@@ -467,7 +468,8 @@ int vm_check_range(struct proc *caller, struct proc *target,
                        (r = caller->p_vmrequest.vmresult) != OK)
                return r;
 
-       vm_suspend(caller, target, vir_addr, bytes, VMSTYPE_KERNELCALL);
+       vm_suspend(caller, target, vir_addr, bytes, VMSTYPE_KERNELCALL,
+               writeflag);
 
        return VMSUSPEND;
 }
@@ -619,7 +621,7 @@ int vm_memset(struct proc* caller, endpoint_t who, phys_bytes ph, int c,
                        /* If a process pagefaults, VM may help out */
                        if (whoptr) {
                                vm_suspend(caller, whoptr, ph, count,
-                                                  VMSTYPE_KERNELCALL);
+                                                  VMSTYPE_KERNELCALL, 1);
                                assert(catch_pagefaults);
                                catch_pagefaults = 0;
                                return VMSUSPEND;
@@ -688,6 +690,7 @@ int vmcheck;                        /* if nonzero, can return VMSUSPEND */
 
   if((r=lin_lin_copy(procs[_SRC_], vir_addr[_SRC_]->offset,
        procs[_DST_], vir_addr[_DST_]->offset, bytes)) != OK) {
+       int writeflag;
        struct proc *target = NULL;
        phys_bytes lin;
        if(r != EFAULT_SRC && r != EFAULT_DST)
@@ -699,9 +702,11 @@ int vmcheck;                       /* if nonzero, can return VMSUSPEND */
        if(r == EFAULT_SRC) {
                lin = vir_addr[_SRC_]->offset;
                target = procs[_SRC_];
+               writeflag = 0;
        } else if(r == EFAULT_DST) {
                lin = vir_addr[_DST_]->offset;
                target = procs[_DST_];
+               writeflag = 1;
        } else {
                panic("r strange: %d",  r);
        }
@@ -709,7 +714,7 @@ int vmcheck;                        /* if nonzero, can return VMSUSPEND */
        assert(caller);
        assert(target);
 
-       vm_suspend(caller, target, lin, bytes, VMSTYPE_KERNELCALL);
+       vm_suspend(caller, target, lin, bytes, VMSTYPE_KERNELCALL, writeflag);
        return VMSUSPEND;
   }
 
index 22ce09521887dc480378d8c8f87ea3f3aa916bbd..0400d6772a8c4cd6fc22c1ad0efdc95c9b138822 100644 (file)
@@ -138,7 +138,7 @@ void hook_ipc_clear(struct proc *proc);
 
 /* system/do_safecopy.c */
 int verify_grant(endpoint_t, endpoint_t, cp_grant_id_t, vir_bytes, int,
-       vir_bytes, vir_bytes *, endpoint_t *);
+       vir_bytes, vir_bytes *, endpoint_t *, u32_t *);
 
 /* system/do_diagctl.c */
 int do_diagctl(struct proc * caller, message *m);
@@ -211,7 +211,7 @@ int arch_phys_map_reply(int index, vir_bytes addr);
 reg_t arch_get_sp(struct proc *p);
 int arch_enable_paging(struct proc * caller);
 int vm_check_range(struct proc *caller,
-       struct proc *target, vir_bytes vir_addr, size_t bytes);
+       struct proc *target, vir_bytes vir_addr, size_t bytes, int writable);
 
 int copy_msg_from_user(message * user_mbuf, message * dst);
 int copy_msg_to_user(message * src, message * user_mbuf);
index e40cdeb2306cb34bc5ad1a04f6326edfb983a43c..2fb61a2a4caed2639f5aafc5e61d20db42a05ad9 100644 (file)
@@ -10,7 +10,9 @@
  */
 
 #include "kernel/system.h"
+#include "kernel/vm.h"
 #include <minix/type.h>
+#include <assert.h>
 
 #if (USE_VIRCOPY || USE_PHYSCOPY)
 
@@ -75,8 +77,16 @@ int do_copy(struct proc * caller, message * m_ptr)
   if (bytes != (phys_bytes) (vir_bytes) bytes) return(E2BIG);
 
   /* Now try to make the actual virtual copy. */
-  return( virtual_copy_vmcheck(caller, &vir_addr[_SRC_],
+  if(m_ptr->CP_FLAGS & CP_FLAG_TRY) {
+       int r;
+       assert(caller->p_endpoint == VFS_PROC_NR);
+       r = virtual_copy(&vir_addr[_SRC_], &vir_addr[_DST_], bytes);
+       if(r == EFAULT_SRC || r == EFAULT_DST) return r = EFAULT;
+       return r;
+  } else {
+       return( virtual_copy_vmcheck(caller, &vir_addr[_SRC_],
                                &vir_addr[_DST_], bytes) );
+  }
 }
 #endif /* (USE_VIRCOPY || USE_PHYSCOPY) */
 
index 80d38fcb3d8307dd912a98a73b02afc74ca67210..62cb6a7c04e8b57d1326a466931ab4ea1ff5ab91 100644 (file)
@@ -17,6 +17,7 @@
 
 #include "kernel/system.h"
 #include "kernel/kernel.h"
+#include "kernel/vm.h"
 
 #define MAX_INDIRECT_DEPTH 5   /* up to how many indirect grants to follow? */
 
@@ -32,7 +33,7 @@ static int safecopy(struct proc *, endpoint_t, endpoint_t,
  *                             verify_grant                                 *
  *===========================================================================*/
 int verify_grant(granter, grantee, grant, bytes, access,
-       offset_in, offset_result, e_granter)
+       offset_in, offset_result, e_granter, flags)
 endpoint_t granter, grantee;   /* copyee, copyer */
 cp_grant_id_t grant;           /* grant id */
 vir_bytes bytes;               /* copy size */
@@ -40,6 +41,7 @@ int access;                   /* direction (read/write) */
 vir_bytes offset_in;           /* copy offset within grant */
 vir_bytes *offset_result;      /* copy offset within virtual address space */
 endpoint_t *e_granter;         /* new granter (magic grants) */
+u32_t *flags;                  /* CPF_* */
 {
        static cp_grant_t g;
        static int proc_nr;
@@ -96,6 +98,8 @@ endpoint_t *e_granter;                /* new granter (magic grants) */
                        return EPERM;
                }
 
+               if(flags) *flags = g.cp_flags;
+
                /* Check validity. */
                if((g.cp_flags & (CPF_USED | CPF_VALID)) !=
                        (CPF_USED | CPF_VALID)) {
@@ -241,6 +245,7 @@ int access;                 /* CPF_READ for a copy from granter to grantee, CPF_WRITE
        endpoint_t new_granter, *src, *dst;
        struct proc *granter_p;
        int r;
+       u32_t flags;
 #if PERF_USE_COW_SAFECOPY
        vir_bytes size;
 #endif
@@ -269,7 +274,7 @@ int access;                 /* CPF_READ for a copy from granter to grantee, CPF_WRITE
 
        /* Verify permission exists. */
        if((r=verify_grant(granter, grantee, grantid, bytes, access,
-           g_offset, &v_offset, &new_granter)) != OK) {
+           g_offset, &v_offset, &new_granter, &flags)) != OK) {
                        printf(
                "grant %d verify to copy %d->%d by %d failed: err %d\n",
                                grantid, *src, *dst, grantee, r);
@@ -298,6 +303,13 @@ int access;                        /* CPF_READ for a copy from granter to grantee, CPF_WRITE
        }
 
        /* Do the regular copy. */
+       if(flags & CPF_TRY) {
+               int r;
+               /* Try copy without transparently faulting in pages. */
+               r = virtual_copy(&v_src, &v_dst, bytes);
+               if(r == EFAULT_SRC || r == EFAULT_DST) return EFAULT;
+               return r;
+       }
        return virtual_copy_vmcheck(caller, &v_src, &v_dst, bytes);
 }
 
index cdd127f85d7ec9b53fed8b02155e369666d0c276..0f9deda38844ffb3befe5700c5ad4561ab372af2 100644 (file)
@@ -47,7 +47,7 @@ int do_safememset(struct proc *caller, message *m_ptr) {
 
        /* Verify permission exists, memset always requires CPF_WRITE */
        r = verify_grant(dst_endpt, caller_endpt, grantid, len, CPF_WRITE,
-                        g_offset, &v_offset, &new_granter);
+                        g_offset, &v_offset, &new_granter, NULL);
 
        if (r != OK) {
                printf("safememset: grant %d verify failed %d", grantid, r);
index 9d0b4065e4157107906defc31310d8cb2686c0f7..7e9c10fc18d4c54e39fc74dbff5f441c6cd6eb27 100644 (file)
@@ -64,7 +64,7 @@ int do_umap_remote(struct proc * caller, message * m_ptr)
        cp_grant_id_t grant = (cp_grant_id_t) offset;
 
         if(verify_grant(targetpr->p_endpoint, grantee, grant, count,
-                0, 0, &newoffset, &newep) != OK) {
+                0, 0, &newoffset, &newep, NULL) != OK) {
                 printf("SYSTEM: do_umap: verify_grant in %s, grant %d, bytes 0x%lx, failed, caller %s\n", targetpr->p_name, offset, count, caller->p_name);
                proc_stacktrace(caller);
                 return EFAULT;
index 56bd635f490e9640bde74dda5774af322833739a..e3fc3152b9513e987fbf37e8b41389e5918b1f70 100644 (file)
@@ -78,7 +78,7 @@ int do_vumap(struct proc *caller, message *m_ptr)
 
        if (source != SELF) {
                r = verify_grant(source, endpt, vvec[i].vv_grant, size, access,
-                       offset, &vir_addr, &granter);
+                       offset, &vir_addr, &granter, NULL);
                if (r != OK)
                        return r;
        } else {
@@ -103,7 +103,7 @@ int do_vumap(struct proc *caller, message *m_ptr)
                        /* This call may suspend the current call, or return an
                         * error for a previous invocation.
                         */
-                       return vm_check_range(caller, procp, vir_addr, size);
+                       return vm_check_range(caller, procp, vir_addr, size, 1);
                }
 
                pvec[pcount].vp_addr = phys_addr;
index 8b6367913b4ec8f2a815f795a7e5004b52843fd3..e590bf2dd79349decb2e0fac73c67417419b046a 100644 (file)
@@ -53,7 +53,7 @@ int libexec_alloc_mmap_ondemand(struct exec_info *execi, vir_bytes vaddr, size_t
 
 int libexec_clearproc_vm_procctl(struct exec_info *execi)
 {
-       return vm_procctl(execi->proc_e, VMPPARAM_CLEAR);
+       return vm_procctl_clear(execi->proc_e);
 }
 
 int libexec_clear_sys_memset(struct exec_info *execi, vir_bytes vaddr, size_t len)
index 9342cf552bd9a0bd95ba51ed015fd84e87bbc634..3cce51b4803994c57eca9f18714162630df69795 100644 (file)
@@ -16,7 +16,7 @@
 #include <string.h>
 
 #define ACCESS_CHECK(a) {                      \
-       if((a) & ~(CPF_READ|CPF_WRITE)) {       \
+       if((a) & ~(CPF_READ|CPF_WRITE|CPF_TRY)) {       \
                errno = EINVAL;                 \
                return -1;                      \
        }                                       \
index 3698332df4b5e8091011e6e19c151d2e1ef4f4ac..28fc890a80caccf39b858c02fe8e58ebdf9f2ba2 100644 (file)
@@ -1,11 +1,12 @@
 #include "syslib.h"
 
-int sys_physcopy(src_proc, src_vir, dst_proc, dst_vir, bytes)
+int sys_physcopy(src_proc, src_vir, dst_proc, dst_vir, bytes, flags)
 endpoint_t src_proc;           /* source process */
 vir_bytes src_vir;             /* source virtual address */
 endpoint_t dst_proc;           /* destination process */
 vir_bytes dst_vir;             /* destination virtual address */
 phys_bytes bytes;              /* how many bytes */
+int flags;                     /* copy flags */
 {
 /* Transfer a block of data.  The source and destination can each either be a
  * process number or SELF (to indicate own process number). Virtual addresses 
@@ -21,12 +22,7 @@ phys_bytes bytes;            /* how many bytes */
   copy_mess.CP_DST_ENDPT = dst_proc;
   copy_mess.CP_DST_ADDR = (long) dst_vir;
   copy_mess.CP_NR_BYTES = (long) bytes;
-
-  /* provide backwards compatability arguments to old
-   * kernels based on process id's; NONE <=> physical
-   */
-  copy_mess.CP_DST_SPACE_OBSOLETE = (dst_proc == NONE ? PHYS_SEG : D_OBSOLETE);
-  copy_mess.CP_SRC_SPACE_OBSOLETE = (src_proc == NONE ? PHYS_SEG : D_OBSOLETE);
+  copy_mess.CP_FLAGS = flags;
 
   return(_kernel_call(SYS_PHYSCOPY, &copy_mess));
 }
index 4140b12a477449f666bacba0c2de4ce961a941b9..a9fae0edddaa2c026fbff35ece4ba4c234db76c1 100644 (file)
@@ -19,11 +19,6 @@ int sys_safecopyfrom(endpoint_t src_e,
   copy_mess.SCP_ADDRESS = (char *) address;
   copy_mess.SCP_BYTES = (long) bytes;
 
-  /* for older kernels that still need the 'seg' field
-   * provide the right value.
-   */
-  copy_mess.SCP_SEG_OBSOLETE = D_OBSOLETE;
-
   return(_kernel_call(SYS_SAFECOPYFROM, &copy_mess));
 
 }
@@ -44,11 +39,6 @@ int sys_safecopyto(endpoint_t dst_e,
   copy_mess.SCP_ADDRESS = (char *) address;
   copy_mess.SCP_BYTES = (long) bytes;
 
-  /* for older kernels that still need the 'seg' field
-   * provide the right value.
-   */
-  copy_mess.SCP_SEG_OBSOLETE = D_OBSOLETE;
-
   return(_kernel_call(SYS_SAFECOPYTO, &copy_mess));
 
 }
index 29e8d2c66292f81c7a74f8bc0a828b46feb0f549..55a6b4a551bd407f93c41bdbae11702e7db61030 100644 (file)
@@ -1,30 +1,28 @@
 #include "syslib.h"
 
 int sys_vircopy(src_proc, src_vir, 
-       dst_proc, dst_vir, bytes)
+       dst_proc, dst_vir, bytes, flags)
 endpoint_t src_proc;           /* source process */
 vir_bytes src_vir;             /* source virtual address */
 endpoint_t dst_proc;           /* destination process */
 vir_bytes dst_vir;             /* destination virtual address */
 phys_bytes bytes;              /* how many bytes */
+int flags;                     /* copy flags */
 {
 /* Transfer a block of data.  The source and destination can each either be a
- * process number or SELF (to indicate own process number). Virtual addresses 
- * are offsets within LOCAL_SEG (text, stack, data), or BIOS_SEG. 
+ * process number or SELF (to indicate own process number).
  */
 
   message copy_mess;
 
   if (bytes == 0L) return(OK);
+  memset(&copy_mess, 0, sizeof(copy_mess));
   copy_mess.CP_SRC_ENDPT = src_proc;
   copy_mess.CP_SRC_ADDR = (long) src_vir;
   copy_mess.CP_DST_ENDPT = dst_proc;
   copy_mess.CP_DST_ADDR = (long) dst_vir;
   copy_mess.CP_NR_BYTES = (long) bytes;
-
-  /* backwards compatability D segs */
-  copy_mess.CP_DST_SPACE_OBSOLETE = D_OBSOLETE;
-  copy_mess.CP_SRC_SPACE_OBSOLETE = D_OBSOLETE;
+  copy_mess.CP_FLAGS = flags;
 
   return(_kernel_call(SYS_VIRCOPY, &copy_mess));
 }
index dad82b9cefb639b1ffda24a7352b889c7d02b61a..84e1dba5c0f21f1652e0fd8cb05269f2247b1385 100644 (file)
@@ -5,9 +5,10 @@
 #include <string.h>
 
 /*===========================================================================*
- *                                vm_exit                                   *
+ *                                vm_procctl                                *
  *===========================================================================*/
-int vm_procctl(endpoint_t ep, int param)
+static int vm_procctl(endpoint_t ep, int param,
+       vir_bytes m1, vir_bytes len, int flags)
 {
     message m;
     int result;
@@ -16,8 +17,22 @@ int vm_procctl(endpoint_t ep, int param)
 
     m.VMPCTL_WHO = ep;
     m.VMPCTL_PARAM = param;
+    m.VMPCTL_M1 = m1;
+    m.VMPCTL_LEN = len;
+    m.VMPCTL_FLAGS = flags;
 
     result = _taskcall(VM_PROC_NR, VM_PROCCTL, &m);
     return(result);
 }
 
+int vm_procctl_clear(endpoint_t ep)
+{
+       return vm_procctl(ep, VMPPARAM_CLEAR, 0, 0, 0);
+}
+
+int vm_procctl_handlemem(endpoint_t ep, vir_bytes m1, vir_bytes len,
+       int writeflag)
+{
+       return vm_procctl(ep, VMPPARAM_HANDLEMEM, m1, len, writeflag);
+}
+
index 0e409e018fa427547b5889eed7227f75737a2fae..fcdda46a26d31717fd6e7487df41be0ec0750eb9 100644 (file)
@@ -92,7 +92,7 @@ int do_sysuname()
        /* Copy an uname string to the user. */
        n = strlen(string) + 1;
        if (n > m_in.PM_SYSUNAME_LEN) n = m_in.PM_SYSUNAME_LEN;
-       r = sys_vircopy(SELF, (phys_bytes) string, 
+       r = sys_datacopy(SELF, (phys_bytes) string, 
                mp->mp_endpoint, (phys_bytes) m_in.PM_SYSUNAME_VALUE,
                (phys_bytes) n);
        if (r < 0) return(r);
@@ -105,7 +105,7 @@ int do_sysuname()
        if (mp->mp_effuid != 0 || len == 0) return(EPERM);
        n = len < m_in.PM_SYSUNAME_LEN ? len : m_in.PM_SYSUNAME_LEN;
        if (n <= 0) return(EINVAL);
-       r = sys_vircopy(mp->mp_endpoint, (phys_bytes) m_in.PM_SYSUNAME_VALUE,
+       r = sys_datacopy(mp->mp_endpoint, (phys_bytes) m_in.PM_SYSUNAME_VALUE,
                SELF, (phys_bytes) tmp, (phys_bytes) n);
        if (r < 0) return(r);
        tmp[n-1] = 0;
index 8644477c80a73a8611a910449e7eac87f8e6c3fc..33c578440021155fe06238ef875e74fd01a44226 100644 (file)
@@ -175,11 +175,11 @@ int do_trace()
        if (req == T_GETRANGE)
                r = sys_vircopy(child->mp_endpoint, (vir_bytes) pr.pr_addr,
                        who_e, (vir_bytes) pr.pr_ptr,
-                       (phys_bytes) pr.pr_size);
+                       (phys_bytes) pr.pr_size, 0);
        else
                r = sys_vircopy(who_e, (vir_bytes) pr.pr_ptr,
                        child->mp_endpoint, (vir_bytes) pr.pr_addr,
-                       (phys_bytes) pr.pr_size);
+                       (phys_bytes) pr.pr_size, 0);
 
        if (r != OK) return(r);
 
index b8215d270d0e7f2f4258fce05b8c2b13e04d33b6..09e0b9a0b39aaf36aff3a235ef35e1acb09e0eb2 100644 (file)
@@ -160,7 +160,7 @@ size_t seg_bytes           /* how much is to be transferred? */
   int r;
 
   if (off+seg_bytes > execi->hdr_len) return ENOEXEC;
-  if((r= sys_vircopy(SELF, ((vir_bytes)execi->hdr)+off,
+  if((r= sys_datacopy(SELF, ((vir_bytes)execi->hdr)+off,
        execi->proc_e, seg_addr, seg_bytes)) != OK) {
        printf("RS: exec read_seg: copy 0x%x bytes into %i at 0x%08lx failed: %i\n",
                seg_bytes, execi->proc_e, seg_addr, r);
index a9480e62411582ba78e9bc68fc05b6c4f16273de..9212998e435ce12fd9bcb7ff63bfc4b6f9991aa5 100755 (executable)
@@ -913,7 +913,7 @@ message *m_ptr;
                return EINVAL;
        }
 
-       if((r=sys_vircopy(m_ptr->m_source, (vir_bytes) m_ptr->RS_NAME,
+       if((r=sys_datacopy(m_ptr->m_source, (vir_bytes) m_ptr->RS_NAME,
                SELF, (vir_bytes) namebuf, len)) != OK) {
                printf("RS: name copy failed\n");
                return r;
index 71e8fcaaa0e81a1acf03b33cbebd668b19d2d53e..663caebb24fe35707ce395abc73f4d0a1a0259bd 100644 (file)
@@ -1,27 +1,29 @@
 #include "fs.h"
 #include <minix/vfsif.h>
 #include <assert.h>
+#include <string.h>
 
-static int sendmsg(struct vmnt *vmp, struct worker_thread *wp);
+static int sendmsg(struct vmnt *vmp, endpoint_t dst, struct worker_thread *wp);
 static int queuemsg(struct vmnt *vmp);
 
 /*===========================================================================*
  *                             sendmsg                                      *
  *===========================================================================*/
-static int sendmsg(struct vmnt *vmp, struct worker_thread *wp)
+static int sendmsg(struct vmnt *vmp, endpoint_t dst, struct worker_thread *wp)
 {
-/* This is the low level function that sends requests to FS processes.
+/* This is the low level function that sends requests.
+ * Currently to FSes or VM.
  */
   int r, transid;
 
-  vmp->m_comm.c_cur_reqs++;    /* One more request awaiting a reply */
+  if(vmp) vmp->m_comm.c_cur_reqs++;    /* One more request awaiting a reply */
   transid = wp->w_tid + VFS_TRANSID;
-  wp->w_fs_sendrec->m_type = TRNS_ADD_ID(wp->w_fs_sendrec->m_type, transid);
-  wp->w_task = vmp->m_fs_e;
-  if ((r = asynsend3(vmp->m_fs_e, wp->w_fs_sendrec, AMF_NOREPLY)) != OK) {
+  wp->w_sendrec->m_type = TRNS_ADD_ID(wp->w_sendrec->m_type, transid);
+  wp->w_task = dst;
+  if ((r = asynsend3(dst, wp->w_sendrec, AMF_NOREPLY)) != OK) {
        printf("VFS: sendmsg: error sending message. "
-               "FS_e: %d req_nr: %d err: %d\n", vmp->m_fs_e,
-               wp->w_fs_sendrec->m_type, r);
+               "dest: %d req_nr: %d err: %d\n", dst,
+                       wp->w_sendrec->m_type, r);
        util_stacktrace();
        return(r);
   }
@@ -78,7 +80,7 @@ void fs_sendmore(struct vmnt *vmp)
   worker->w_next = NULL;
   sending--;
   assert(sending >= 0);
-  (void) sendmsg(vmp, worker);
+  (void) sendmsg(vmp, vmp->m_fs_e, worker);
 }
 
 /*===========================================================================*
@@ -139,13 +141,13 @@ int fs_sendrec(endpoint_t fs_e, message *reqmp)
   }
   if (fs_e == fp->fp_endpoint) return(EDEADLK);
 
-  self->w_fs_sendrec = reqmp;  /* Where to store request and reply */
+  self->w_sendrec = reqmp;     /* Where to store request and reply */
 
   /* Find out whether we can send right away or have to enqueue */
   if ( !(vmp->m_flags & VMNT_CALLBACK) &&
        vmp->m_comm.c_cur_reqs < vmp->m_comm.c_max_reqs) {
        /* There's still room to send more and no proc is queued */
-       r = sendmsg(vmp, self);
+       r = sendmsg(vmp, vmp->m_fs_e, self);
   } else {
        r = queuemsg(vmp);
   }
@@ -158,6 +160,53 @@ int fs_sendrec(endpoint_t fs_e, message *reqmp)
   return(reqmp->m_type);
 }
 
+/*===========================================================================*
+ *                             vm_sendrec                                   *
+ *===========================================================================*/
+int vm_sendrec(message *reqmp)
+{
+  int r;
+
+  assert(self);
+  assert(reqmp);
+
+  self->w_sendrec = reqmp;     /* Where to store request and reply */
+
+  r = sendmsg(NULL, VM_PROC_NR, self);
+
+  self->w_next = NULL; /* End of list */
+
+  if (r != OK) return(r);
+
+  worker_wait();       /* Yield execution until we've received the reply. */
+
+  return(reqmp->m_type);
+}
+
+
+/*===========================================================================*
+ *                                vm_vfs_procctl_handlemem                   *
+ *===========================================================================*/
+int vm_vfs_procctl_handlemem(endpoint_t ep,
+        vir_bytes mem, vir_bytes len, int flags)
+{
+    message m;
+
+    /* main thread can not be suspended */
+    if(!self) return EFAULT;
+
+    memset(&m, 0, sizeof(m));
+
+    m.m_type = VM_PROCCTL;
+    m.VMPCTL_WHO = ep;
+    m.VMPCTL_PARAM = VMPPARAM_HANDLEMEM;
+    m.VMPCTL_M1 = mem;
+    m.VMPCTL_LEN = len;
+    m.VMPCTL_FLAGS = flags;
+
+    return vm_sendrec(&m);
+}
+
 /*===========================================================================*
  *                             queuemsg                                     *
  *===========================================================================*/
index a4068d14d4b91ce81652054b7626838c1afd4a1e..0de129240cfe2452669b7b99bfb2807e85926826 100644 (file)
@@ -303,7 +303,7 @@ static void dump_segments(struct filp *f, Elf_Phdr phdrs[], int phnum)
 
        for (off = 0; off < (off_t) len; off += CLICK_SIZE) {
                vir_bytes p = (vir_bytes) (seg_off + off);
-               r = sys_vircopy(fp->fp_endpoint, p,
+               r = sys_datacopy_try(fp->fp_endpoint, p,
                        SELF, (vir_bytes) buf,
                        (phys_bytes) CLICK_SIZE);
 
index 6a411661ce70ff28710d9be10904ad489664675c..b4cbe131a9f8fce79210ed5888d88bbefcffcdbd 100644 (file)
@@ -129,7 +129,8 @@ int do_mapdriver(void)
        printf("VFS: do_mapdriver: label too long\n");
        return(EINVAL);
   }
-  r = sys_vircopy(who_e, label_vir, SELF, (vir_bytes) label, label_len);
+  r = sys_vircopy(who_e, label_vir, SELF, (vir_bytes) label, label_len,
+       CP_FLAG_TRY);
   if (r != OK) {
        printf("VFS: do_mapdriver: sys_vircopy failed: %d\n", r);
        return(EINVAL);
index ca12ddd281d9ee994b204d5ea6db8f8d084ff7e2..14c36a172192f87e27d35fc263894cd619b2ed53 100644 (file)
@@ -228,7 +228,7 @@ int pm_exec(vir_bytes path, size_t path_len, vir_bytes frame, size_t frame_len,
   if (frame_len > ARG_MAX)
        FAILCHECK(ENOMEM); /* stack too big */
 
-  r = sys_datacopy(fp->fp_endpoint, (vir_bytes) frame, SELF, (vir_bytes) mbuf,
+  r = sys_datacopy_wrapper(fp->fp_endpoint, (vir_bytes) frame, SELF, (vir_bytes) mbuf,
                   (size_t) frame_len);
   if (r != OK) { /* can't fetch stack (e.g. bad virtual addr) */
         printf("VFS: pm_exec: sys_datacopy failed\n");
@@ -362,7 +362,7 @@ int pm_exec(vir_bytes path, size_t path_len, vir_bytes frame, size_t frame_len,
   if(makestack) FAILCHECK(makestack(&execi, mbuf, &frame_len, &vsp));
 
   /* Copy the stack from VFS to new core image. */
-  FAILCHECK(sys_datacopy(SELF, (vir_bytes) mbuf, fp->fp_endpoint,
+  FAILCHECK(sys_datacopy_wrapper(SELF, (vir_bytes) mbuf, fp->fp_endpoint,
        (vir_bytes) vsp, (phys_bytes)frame_len));
 
   /* Return new stack pointer to caller */
index 30fc30bc55ddde8a2a0aacfc86b55859ae9af627..e9c63fcdd57303619781fdd4dc2acab5fd59a912 100644 (file)
@@ -31,7 +31,7 @@ int req;                      /* either F_SETLK or F_SETLKW */
   struct file_lock *flp, *flp2, *empty;
 
   /* Fetch the flock structure from user space. */
-  r = sys_datacopy(who_e, (vir_bytes) scratch(fp).io.io_buffer, VFS_PROC_NR,
+  r = sys_datacopy_wrapper(who_e, (vir_bytes) scratch(fp).io.io_buffer, VFS_PROC_NR,
                   (vir_bytes) &flock, sizeof(flock));
   if (r != OK) return(EINVAL);
 
@@ -141,7 +141,7 @@ int req;                    /* either F_SETLK or F_SETLKW */
        }
 
        /* Copy the flock structure back to the caller. */
-       r = sys_datacopy(VFS_PROC_NR, (vir_bytes) &flock, who_e,
+       r = sys_datacopy_wrapper(VFS_PROC_NR, (vir_bytes) &flock, who_e,
                (vir_bytes) scratch(fp).io.io_buffer, sizeof(flock));
        return(r);
   }
index 1e00997672b57e1f0dba1b10e39fb213495d4b96..e781a49975745efe5b953fde25d86fe8ecab4742 100644 (file)
@@ -35,7 +35,7 @@ EXTERN unsigned long calls_stats[NR_VFS_CALLS];
 #endif
 
 /* Thread related prototypes */
-static void do_fs_reply(struct worker_thread *wp);
+static void do_reply(struct worker_thread *wp);
 static void do_work(void);
 static void do_init_root(void);
 static void handle_work(void (*func)(void));
@@ -86,7 +86,7 @@ int main(void)
                        continue;
                }
                m_in.m_type = TRNS_DEL_ID(m_in.m_type);
-               do_fs_reply(wp);
+               do_reply(wp);
                continue;
        } else if (who_e == PM_PROC_NR) { /* Calls from PM */
                /* Special control messages from PM */
@@ -179,22 +179,22 @@ static void handle_work(void (*func)(void))
 
 
 /*===========================================================================*
- *                            do_fs_reply                                   *
+ *                            do_reply                                      *
  *===========================================================================*/
-static void do_fs_reply(struct worker_thread *wp)
+static void do_reply(struct worker_thread *wp)
 {
-  struct vmnt *vmp;
+  struct vmnt *vmp = NULL;
 
-  if ((vmp = find_vmnt(who_e)) == NULL)
+  if(who_e != VM_PROC_NR && (vmp = find_vmnt(who_e)) == NULL)
        panic("Couldn't find vmnt for endpoint %d", who_e);
 
   if (wp->w_task != who_e) {
-       printf("VFS: expected %d to reply, not %d\n", wp->w_task, who_e);
-       return;
+       printf("VFS: tid %d: expected %d to reply, not %d\n",
+               wp->w_tid, wp->w_task, who_e);
   }
-  *wp->w_fs_sendrec = m_in;
+  *wp->w_sendrec = m_in;
   wp->w_task = NONE;
-  vmp->m_comm.c_cur_reqs--; /* We've got our reply, make room for others */
+  if(vmp) vmp->m_comm.c_cur_reqs--; /* We've got our reply, make room for others */
   worker_signal(wp); /* Continue this thread */
 }
 
index 7dcbb3276875569c25f482c855bfb1f3263e8886..d9548cbda17089c5e36844cde7a5ec068b1da70b 100644 (file)
@@ -89,7 +89,7 @@ int do_getsysinfo(void)
   if (len != buf_size)
        return(EINVAL);
 
-  return sys_datacopy(SELF, src_addr, who_e, dst_addr, len);
+  return sys_datacopy_wrapper(SELF, src_addr, who_e, dst_addr, len);
 }
 
 /*===========================================================================*
@@ -170,7 +170,7 @@ int do_fcntl(void)
        else if (!(f->filp_mode & W_BIT)) r = EBADF;
        else {
                /* Copy flock data from userspace. */
-               r = sys_datacopy(who_e, (vir_bytes) scratch(fp).io.io_buffer,
+               r = sys_datacopy_wrapper(who_e, (vir_bytes) scratch(fp).io.io_buffer,
                        SELF, (vir_bytes) &flock_arg, sizeof(flock_arg));
        }
 
@@ -709,7 +709,7 @@ gid_t *groups;
   rfp = &fproc[slot];
   if (ngroups * sizeof(gid_t) > sizeof(rfp->fp_sgroups))
        panic("VFS: pm_setgroups: too much data to copy");
-  if (sys_datacopy(who_e, (vir_bytes) groups, SELF, (vir_bytes) rfp->fp_sgroups,
+  if (sys_datacopy_wrapper(who_e, (vir_bytes) groups, SELF, (vir_bytes) rfp->fp_sgroups,
                   ngroups * sizeof(gid_t)) == OK) {
        rfp->fp_ngroups = ngroups;
   } else
@@ -775,7 +775,7 @@ int do_svrctl(void)
                int r, s;
 
                /* Copy sysgetenv structure to VFS */
-               if (sys_datacopy(who_e, ptr, SELF, (vir_bytes) &sysgetenv,
+               if (sys_datacopy_wrapper(who_e, ptr, SELF, (vir_bytes) &sysgetenv,
                                 sizeof(sysgetenv)) != OK)
                        return(EFAULT);
 
@@ -790,7 +790,7 @@ int do_svrctl(void)
                }
 
                /* Copy parameter "key" */
-               if ((s = sys_datacopy(who_e, (vir_bytes) sysgetenv.key,
+               if ((s = sys_datacopy_wrapper(who_e, (vir_bytes) sysgetenv.key,
                                      SELF, (vir_bytes) search_key,
                                      sysgetenv.keylen)) != OK)
                        return(s);
@@ -800,7 +800,7 @@ int do_svrctl(void)
                if (svrctl == VFSSETPARAM) {
                        if (!strcmp(search_key, "verbose")) {
                                int verbose_val;
-                               if ((s = sys_datacopy(who_e,
+                               if ((s = sys_datacopy_wrapper(who_e,
                                    (vir_bytes) sysgetenv.val, SELF,
                                    (vir_bytes) &val, sysgetenv.vallen)) != OK)
                                        return(s);
@@ -832,12 +832,12 @@ int do_svrctl(void)
                        }
 
                        if (r == OK) {
-                               if ((s = sys_datacopy(SELF,
+                               if ((s = sys_datacopy_wrapper(SELF,
                                    (vir_bytes) &sysgetenv, who_e, ptr,
                                    sizeof(sysgetenv))) != OK)
                                        return(s);
                                if (sysgetenv.val != 0) {
-                                       if ((s = sys_datacopy(SELF,
+                                       if ((s = sys_datacopy_wrapper(SELF,
                                            (vir_bytes) small_buf, who_e,
                                            (vir_bytes) sysgetenv.val,
                                            sysgetenv.vallen)) != OK)
@@ -875,7 +875,7 @@ int pm_dumpcore(int csig, vir_bytes exe_name)
   if (core_fd < 0) { r = core_fd; goto core_exit; }
 
   /* get process' name */
-  r = sys_datacopy(PM_PROC_NR, exe_name, VFS_PROC_NR, (vir_bytes) proc_name,
+  r = sys_datacopy_wrapper(PM_PROC_NR, exe_name, VFS_PROC_NR, (vir_bytes) proc_name,
                        PROC_NAME_LEN);
   if (r != OK) goto core_exit;
   proc_name[PROC_NAME_LEN - 1] = '\0';
@@ -943,7 +943,7 @@ int do_getrusage(void)
        int res;
        struct rusage r_usage;
 
-       if ((res = sys_datacopy(who_e, (vir_bytes) m_in.RU_RUSAGE_ADDR, SELF,
+       if ((res = sys_datacopy_wrapper(who_e, (vir_bytes) m_in.RU_RUSAGE_ADDR, SELF,
                (vir_bytes) &r_usage, (vir_bytes) sizeof(r_usage))) < 0)
                return res;
 
@@ -953,6 +953,6 @@ int do_getrusage(void)
        r_usage.ru_idrss = fp->data_size;
        r_usage.ru_isrss = DEFAULT_STACK_LIMIT;
 
-       return sys_datacopy(SELF, (vir_bytes) &r_usage, who_e,
+       return sys_datacopy_wrapper(SELF, (vir_bytes) &r_usage, who_e,
                (vir_bytes) m_in.RU_RUSAGE_ADDR, (phys_bytes) sizeof(r_usage));
 }
index a97d1ea01bae925fdd0cafc2393e212afc559e15..6d8ef411c3d31d31399b586ee9711a57606d33dd 100644 (file)
@@ -109,7 +109,7 @@ int do_mount(void)
   /* Get the label from the caller, and ask DS for the endpoint of the FS. */
   if (label_len > sizeof(mount_label))
        return EINVAL;
-  r = sys_datacopy(who_e, label, SELF, (vir_bytes) mount_label,
+  r = sys_datacopy_wrapper(who_e, label, SELF, (vir_bytes) mount_label,
        sizeof(mount_label));
   if (r != OK) return(r);
 
@@ -446,7 +446,7 @@ int do_umount(void)
    */
   if (strlen(label) >= label_len)
        label[label_len-1] = 0;
-  return sys_datacopy(SELF, (vir_bytes) label, who_e, label_addr,
+  return sys_datacopy_wrapper(SELF, (vir_bytes) label, who_e, label_addr,
        strlen(label) + 1);
 }
 
index 941072e075c735622acff3d6fc5f7ab3e9d70074..cdf98fc5969a52625575e74194224552b7cfe3ff 100644 (file)
@@ -24,8 +24,10 @@ struct job;
 int drv_sendrec(endpoint_t drv_e, message *reqm);
 void fs_cancel(struct vmnt *vmp);
 int fs_sendrec(endpoint_t fs_e, message *reqm);
+int vm_sendrec(message *reqm);
 void fs_sendmore(struct vmnt *vmp);
 void send_work(void);
+int vm_vfs_procctl_handlemem(endpoint_t ep, vir_bytes mem, vir_bytes len, int flags);
 
 /* device.c */
 int cdev_open(dev_t dev, int flags);
@@ -277,6 +279,8 @@ int copy_path(char *dest, size_t size);
 int fetch_name(vir_bytes path, size_t len, char *dest);
 int isokendpt_f(const char *f, int l, endpoint_t e, int *p, int ft);
 int in_group(struct fproc *rfp, gid_t grp);
+int sys_datacopy_wrapper(endpoint_t src, vir_bytes srcv, endpoint_t dst, vir_bytes dstv,
+       size_t len);
 
 #define okendpt(e, p) isokendpt_f(__FILE__, __LINE__, (e), (p), 1)
 #define isokendpt(e, p) isokendpt_f(__FILE__, __LINE__, (e), (p), 0)
index 09389dc1a9d93212962fd06ec7a1da388be7b52a..a68d2eea93aced5429e4d93046bd5b2337021519 100644 (file)
 
 
 /*===========================================================================*
- *                     req_breadwrite                                       *
+ *                     req_breadwrite_actual                                *
  *===========================================================================*/
-int req_breadwrite(
-  endpoint_t fs_e,
-  endpoint_t user_e,
-  dev_t dev,
-  off_t pos,
-  unsigned int num_of_bytes,
-  vir_bytes user_addr,
-  int rw_flag,
-  off_t *new_pos,
-  unsigned int *cum_iop
-)
+static int req_breadwrite_actual(endpoint_t fs_e, endpoint_t user_e, dev_t dev, off_t pos,
+        unsigned int num_of_bytes, vir_bytes user_addr, int rw_flag,
+        off_t *new_pos, unsigned int *cum_iop, int cpflag)
 {
   int r;
   cp_grant_id_t grant_id;
   message m;
 
   grant_id = cpf_grant_magic(fs_e, user_e, user_addr, num_of_bytes,
-                       (rw_flag == READING ? CPF_WRITE : CPF_READ));
+                       (rw_flag == READING ? CPF_WRITE : CPF_READ) | cpflag);
   if(grant_id == -1)
          panic("req_breadwrite: cpf_grant_magic failed");
 
@@ -67,6 +59,28 @@ int req_breadwrite(
   return(OK);
 }
 
+int req_breadwrite(endpoint_t fs_e, endpoint_t user_e, dev_t dev, off_t pos,
+        unsigned int num_of_bytes, vir_bytes user_addr, int rw_flag,
+        off_t *new_pos, unsigned int *cum_iop)
+{
+       int r;
+
+       r = req_breadwrite_actual(fs_e, user_e, dev, pos, num_of_bytes,
+               user_addr, rw_flag, new_pos, cum_iop, CPF_TRY);
+
+       if(r == EFAULT) {
+               if((r=vm_vfs_procctl_handlemem(user_e, user_addr, num_of_bytes,
+                       rw_flag == READING)) != OK) {
+                       return r;
+               }
+
+               r = req_breadwrite_actual(fs_e, user_e, dev, pos, num_of_bytes,
+                       user_addr, rw_flag, new_pos, cum_iop, 0);
+       }
+
+       return r;
+}
+
 /*===========================================================================*
  *                     req_bpeek                                            *
  *===========================================================================*/
@@ -267,16 +281,17 @@ int req_ftrunc(endpoint_t fs_e, ino_t inode_nr, off_t start, off_t end)
 
 
 /*===========================================================================*
- *                             req_getdents                                 *
+ *                             req_getdents_actual                          *
  *===========================================================================*/
-int req_getdents(
+static int req_getdents_actual(
   endpoint_t fs_e,
   ino_t inode_nr,
   off_t pos,
   char *buf,
   size_t size,
   off_t *new_pos,
-  int direct
+  int direct,
+  int cpflag
 )
 {
   int r;
@@ -291,7 +306,7 @@ int req_getdents(
        grant_id = cpf_grant_direct(fs_e, (vir_bytes) buf, size, CPF_WRITE);
   } else {
        grant_id = cpf_grant_magic(fs_e, who_e, (vir_bytes) buf, size,
-                                  CPF_WRITE);
+                                  CPF_WRITE | cpflag);
   }
 
   if (grant_id < 0)
@@ -319,6 +334,36 @@ int req_getdents(
   return(r);
 }
 
+/*===========================================================================*
+ *                             req_getdents                                 *
+ *===========================================================================*/
+int req_getdents(
+  endpoint_t fs_e,
+  ino_t inode_nr,
+  off_t pos,
+  char *buf,
+  size_t size,
+  off_t *new_pos,
+  int direct)
+{
+       int r;
+
+       r = req_getdents_actual(fs_e, inode_nr, pos, buf, size, new_pos,
+               direct, CPF_TRY);
+
+       if(r == EFAULT && !direct) {
+               if((r=vm_vfs_procctl_handlemem(who_e, (vir_bytes) buf,
+                       size, 1)) != OK) {
+                       return r;
+               }
+
+               r = req_getdents_actual(fs_e, inode_nr, pos, buf, size,
+                       new_pos, direct, 0);
+       }
+
+       return r;
+}
+
 /*===========================================================================*
  *                             req_inhibread                                *
  *===========================================================================*/
@@ -665,15 +710,12 @@ int count;
 
 
 /*===========================================================================*
- *                             req_rdlink                                   *
+ *                             req_rdlink_actual                            *
  *===========================================================================*/
-int req_rdlink(fs_e, inode_nr, proc_e, buf, len, direct)
-endpoint_t fs_e;
-ino_t inode_nr;
-endpoint_t proc_e;
-vir_bytes buf;
-size_t len;
-int direct; /* set to 1 to use direct grants instead of magic grants */
+static int req_rdlink_actual(endpoint_t fs_e, ino_t inode_nr,
+       endpoint_t proc_e, vir_bytes buf, size_t len,
+       int direct, /* set to 1 to use direct grants instead of magic grants */
+       int cpflag)
 {
   message m;
   int r;
@@ -682,7 +724,7 @@ int direct; /* set to 1 to use direct grants instead of magic grants */
   if (direct) {
        grant_id = cpf_grant_direct(fs_e, buf, len, CPF_WRITE);
   } else {
-       grant_id = cpf_grant_magic(fs_e, proc_e, buf, len, CPF_WRITE);
+       grant_id = cpf_grant_magic(fs_e, proc_e, buf, len, CPF_WRITE | cpflag);
   }
   if (grant_id == -1)
          panic("req_rdlink: cpf_grant_magic failed");
@@ -702,6 +744,30 @@ int direct; /* set to 1 to use direct grants instead of magic grants */
   return(r);
 }
 
+/*===========================================================================*
+ *                             req_rdlink                                   *
+ *===========================================================================*/
+int req_rdlink(endpoint_t fs_e, ino_t inode_nr, endpoint_t proc_e,
+       vir_bytes buf, size_t len,
+       int direct /* set to 1 to use direct grants instead of magic grants */
+)
+{
+       int r;
+
+       r = req_rdlink_actual(fs_e, inode_nr, proc_e, buf, len, direct,
+               CPF_TRY);
+
+       if(r == EFAULT && !direct) {
+               if((r=vm_vfs_procctl_handlemem(proc_e, buf, len, 1)) != OK) {
+                       return r;
+               }
+
+               r = req_rdlink_actual(fs_e, inode_nr, proc_e, buf, len,
+                       direct, 0);
+       }
+
+       return r;
+}
 
 /*===========================================================================*
  *                             req_readsuper                                *
@@ -758,18 +824,12 @@ int req_readsuper(
 
 
 /*===========================================================================*
- *                             req_readwrite                                *
+ *                             req_readwrite_actual                         *
  *===========================================================================*/
-int req_readwrite(
-endpoint_t fs_e,
-ino_t inode_nr,
-off_t pos,
-int rw_flag,
-endpoint_t user_e,
-vir_bytes user_addr,
-unsigned int num_of_bytes,
-off_t *new_posp,
-unsigned int *cum_iop)
+static int req_readwrite_actual(endpoint_t fs_e, ino_t inode_nr, off_t pos,
+       int rw_flag, endpoint_t user_e, vir_bytes user_addr,
+       unsigned int num_of_bytes, off_t *new_posp, unsigned int *cum_iop,
+       int cpflag)
 {
   struct vmnt *vmp;
   int r;
@@ -779,7 +839,7 @@ unsigned int *cum_iop)
   vmp = find_vmnt(fs_e);
 
   grant_id = cpf_grant_magic(fs_e, user_e, user_addr, num_of_bytes,
-                            (rw_flag==READING ? CPF_WRITE:CPF_READ));
+                            (rw_flag==READING ? CPF_WRITE:CPF_READ) | cpflag);
   if (grant_id == -1)
          panic("req_readwrite: cpf_grant_magic failed");
 
@@ -806,6 +866,31 @@ unsigned int *cum_iop)
   return(r);
 }
 
+/*===========================================================================*
+ *                             req_readwrite                                *
+ *===========================================================================*/
+int req_readwrite(endpoint_t fs_e, ino_t inode_nr, off_t pos,
+       int rw_flag, endpoint_t user_e, vir_bytes user_addr,
+       unsigned int num_of_bytes, off_t *new_posp, unsigned int *cum_iop)
+{
+       int r;
+
+       r = req_readwrite_actual(fs_e, inode_nr, pos, rw_flag, user_e,
+               user_addr, num_of_bytes, new_posp, cum_iop, CPF_TRY);
+
+       if(r == EFAULT) {
+               if((r=vm_vfs_procctl_handlemem(user_e, (vir_bytes) user_addr, num_of_bytes,
+                       rw_flag == READING)) != OK) {
+                       return r;
+               }
+
+               r = req_readwrite_actual(fs_e, inode_nr, pos, rw_flag, user_e,
+                       user_addr, num_of_bytes, new_posp, cum_iop, 0);
+       }
+
+       return r;
+}
+
 /*===========================================================================*
  *                             req_peek                                     *
  *===========================================================================*/
@@ -905,9 +990,9 @@ char *lastc;
 
 
 /*===========================================================================*
- *                             req_slink                                    *
+ *                             req_slink_actual                             *
  *===========================================================================*/
-int req_slink(
+static int req_slink_actual(
   endpoint_t fs_e,
   ino_t inode_nr,
   char *lastc,
@@ -915,7 +1000,8 @@ int req_slink(
   vir_bytes path_addr,
   size_t path_length,
   uid_t uid,
-  gid_t gid
+  gid_t gid,
+  int cpflag
 )
 {
   int r;
@@ -928,7 +1014,9 @@ int req_slink(
   if (gid_name == GRANT_INVALID)
          panic("req_slink: cpf_grant_direct failed");
 
-  gid_buf = cpf_grant_magic(fs_e, proc_e, path_addr, path_length, CPF_READ);
+  gid_buf = cpf_grant_magic(fs_e, proc_e, path_addr, path_length,
+       CPF_READ | cpflag);
+
   if (gid_buf == GRANT_INVALID) {
          cpf_revoke(gid_name);
          panic("req_slink: cpf_grant_magic failed");
@@ -952,18 +1040,51 @@ int req_slink(
   return(r);
 }
 
+/*===========================================================================*
+ *                             req_slink                                    *
+ *===========================================================================*/
+int req_slink(
+  endpoint_t fs_e,
+  ino_t inode_nr,
+  char *lastc,
+  endpoint_t proc_e,
+  vir_bytes path_addr,
+  size_t path_length,
+  uid_t uid,
+  gid_t gid
+)
+{
+       int r;
+
+       r = req_slink_actual(fs_e, inode_nr, lastc, proc_e, path_addr,
+               path_length, uid, gid, CPF_TRY);
+
+       if(r == EFAULT) {
+               if((r=vm_vfs_procctl_handlemem(proc_e, (vir_bytes) path_addr,
+                       path_length, 0)) != OK) {
+                       return r;
+               }
+
+               r = req_slink_actual(fs_e, inode_nr, lastc, proc_e, path_addr,
+                       path_length, uid, gid, 0);
+       }
+
+       return r;
+}
 
 /*===========================================================================*
- *                             req_stat                                     *
+ *                             req_stat_actual                              *
  *===========================================================================*/
-int req_stat(endpoint_t fs_e, ino_t inode_nr, endpoint_t proc_e, vir_bytes buf)
+int req_stat_actual(endpoint_t fs_e, ino_t inode_nr, endpoint_t proc_e,
+       vir_bytes buf, int cpflag)
 {
   cp_grant_id_t grant_id;
   int r;
   message m;
 
   /* Grant FS access to copy straight into user provided buffer */
-  grant_id = cpf_grant_magic(fs_e, proc_e, buf, sizeof(struct stat), CPF_WRITE);
+  grant_id = cpf_grant_magic(fs_e, proc_e, buf, sizeof(struct stat),
+       CPF_WRITE | cpflag);
 
   if (grant_id < 0)
        panic("req_stat: cpf_grant_* failed");
@@ -981,6 +1102,28 @@ int req_stat(endpoint_t fs_e, ino_t inode_nr, endpoint_t proc_e, vir_bytes buf)
 }
 
 
+/*===========================================================================*
+ *                             req_stat                                     *
+ *===========================================================================*/
+int req_stat(endpoint_t fs_e, ino_t inode_nr, endpoint_t proc_e,
+       vir_bytes buf)
+{
+       int r;
+
+       r = req_stat_actual(fs_e, inode_nr, proc_e, buf, CPF_TRY);
+
+       if(r == EFAULT) {
+               if((r=vm_vfs_procctl_handlemem(proc_e, (vir_bytes) buf,
+                       sizeof(struct stat), 1)) != OK) {
+                       return r;
+               }
+
+               r = req_stat_actual(fs_e, inode_nr, proc_e, buf, 0);
+       }
+
+       return r;
+}
+
 /*===========================================================================*
  *                             req_sync                                     *
  *===========================================================================*/
index 537e4d879532111d096921982a499c46c5590767..945be2cf8fb3469b1dcda4fd5bf25b1c920148ee 100644 (file)
@@ -126,7 +126,7 @@ int do_select(void)
   /* Did the process set a timeout value? If so, retrieve it. */
   if (vtimeout != 0) {
        do_timeout = 1;
-       r = sys_vircopy(who_e, (vir_bytes) vtimeout, SELF, 
+       r = sys_datacopy_wrapper(who_e, (vir_bytes) vtimeout, SELF, 
                        (vir_bytes) &timeout, sizeof(timeout));
        if (r != OK) {
                se->requestor = NULL;
@@ -535,7 +535,7 @@ static int copy_fdsets(struct selectentry *se, int nfds, int direction)
   src_fds = (direction == FROM_PROC) ? se->vir_readfds : &se->ready_readfds;
   dst_fds = (direction == FROM_PROC) ? &se->readfds : se->vir_readfds;
   if (se->vir_readfds) {
-       r = sys_vircopy(src_e, (vir_bytes) src_fds, dst_e, 
+       r = sys_datacopy_wrapper(src_e, (vir_bytes) src_fds, dst_e, 
                        (vir_bytes) dst_fds, fd_setsize);
        if (r != OK) return(r);
   }
@@ -544,7 +544,7 @@ static int copy_fdsets(struct selectentry *se, int nfds, int direction)
   src_fds = (direction == FROM_PROC) ? se->vir_writefds : &se->ready_writefds;
   dst_fds = (direction == FROM_PROC) ? &se->writefds : se->vir_writefds;
   if (se->vir_writefds) {
-       r = sys_vircopy(src_e, (vir_bytes) src_fds, dst_e, 
+       r = sys_datacopy_wrapper(src_e, (vir_bytes) src_fds, dst_e, 
                        (vir_bytes) dst_fds, fd_setsize);
        if (r != OK) return(r);
   }
@@ -553,7 +553,7 @@ static int copy_fdsets(struct selectentry *se, int nfds, int direction)
   src_fds = (direction == FROM_PROC) ? se->vir_errorfds : &se->ready_errorfds;
   dst_fds = (direction == FROM_PROC) ? &se->errorfds : se->vir_errorfds;
   if (se->vir_errorfds) {
-       r = sys_vircopy(src_e, (vir_bytes) src_fds, dst_e, 
+       r = sys_datacopy_wrapper(src_e, (vir_bytes) src_fds, dst_e, 
                        (vir_bytes) dst_fds, fd_setsize);
        if (r != OK) return(r);
   }
index 971fc68307d185dcf0c7ec5342158d1c527fb486..b8dfc087f01c470a143bdc1230730d613283b672 100644 (file)
@@ -284,7 +284,8 @@ static int fill_statvfs(struct vmnt *vmp, endpoint_t endpt, vir_bytes buf_addr,
   strlcpy(buf.f_mntonname, vmp->m_mount_path, sizeof(buf.f_mntonname));
   strlcpy(buf.f_mntfromname, vmp->m_mount_dev, sizeof(buf.f_mntfromname));
 
-  return sys_datacopy(SELF, (vir_bytes) &buf, endpt, buf_addr, sizeof(buf));
+  return sys_datacopy_wrapper(SELF, (vir_bytes) &buf,
+       endpt, buf_addr, sizeof(buf));
 }
 
 /*===========================================================================*
index 6758cd123118e1887408a223da97ad192bea8693..b4a30689db4c12f22b900c07145e2ff3b0295dc5 100644 (file)
@@ -31,7 +31,7 @@ struct worker_thread {
   message w_m_in;
   message w_m_out;
   int w_err_code;
-  message *w_fs_sendrec;
+  message *w_sendrec;
   message *w_drv_sendrec;
   endpoint_t w_task;
   struct dmap *w_dmap;
index b3437edbef44cbd13fcf52ffeae582ff5fa0e516..4f4e4ed492b8eaf9877eda7742adeb8af48e2ee1 100644 (file)
@@ -75,7 +75,7 @@ int fetch_name(vir_bytes path, size_t len, char *dest)
   }
 
   /* String is not contained in the message.  Get it from user space. */
-  r = sys_datacopy(who_e, path, VFS_PROC_NR, (vir_bytes) dest, len);
+  r = sys_datacopy_wrapper(who_e, path, VFS_PROC_NR, (vir_bytes) dest, len);
   if (r != OK) {
        err_code = EINVAL;
        return(r);
@@ -164,3 +164,52 @@ int in_group(struct fproc *rfp, gid_t grp)
 
   return(EINVAL);
 }
+
+/*===========================================================================*
+ *                              sys_datacopy_wrapper                         *
+ *===========================================================================*/
+int sys_datacopy_wrapper(endpoint_t src, vir_bytes srcv,
+       endpoint_t dst, vir_bytes dstv, size_t len)
+{
+       /* Safe function to copy data from or to a user buffer.
+        * VFS has to be a bit more careful as a regular copy
+        * might trigger VFS action needed by VM while it's
+        * blocked on the kernel call. This wrapper tries the
+        * copy, invokes VM itself asynchronously if necessary,
+        * then tries the copy again.
+        *
+        * This function assumes it's between VFS and a user process,
+        * and therefore one of the endpoints is SELF (VFS).
+        */
+       int r;
+       endpoint_t them = NONE;
+       vir_bytes themv = -1;
+       int writable = -1;
+
+       r = sys_datacopy_try(src, srcv, dst, dstv, len);
+
+       if(src == VFS_PROC_NR) src = SELF;
+       if(dst == VFS_PROC_NR) dst = SELF;
+
+       assert(src == SELF || dst == SELF);
+
+       if(src == SELF) { them = dst; themv = dstv; writable = 1; }
+       if(dst == SELF) { them = src; themv = srcv; writable = 0; }
+
+       assert(writable >= 0);
+       assert(them != SELF);
+
+       if(r == EFAULT) {
+               /* The copy has failed with EFAULT, this means the kernel has
+                * given up but it might not be a legitimate error. Ask VM.
+                */
+               if((r=vm_vfs_procctl_handlemem(them, themv, len, writable)) != OK) {
+                       return r;
+               }
+
+               r = sys_datacopy_try(src, srcv, dst, dstv, len);
+       }
+
+       return r;
+}
+
index 438c057ba03d331e5755da271c9ed6e67b000324..a45b3d885dfc029041641c1be9fb910b56b4c6ae 100644 (file)
@@ -47,7 +47,7 @@ void check_vnode_locks_by_me(struct fproc *rfp)
 
   for (vp = &vnode[0]; vp < &vnode[NR_VNODES]; vp++) {
        if (tll_locked_by_me(&vp->v_lock)) {
-               panic("Thread %d still holds vnode lock on vp %x call_nr=%d\n",
+               panic("Thread %d still holds vnode lock on vp %p call_nr=%d\n",
                      mthread_self(), vp, job_call_nr);
        }
   }
index 8c1f0d771a67234e5838334b816933a8d896a37d..fe026a6f265df29663b84479572a2a7e99fdfee7 100644 (file)
@@ -37,6 +37,7 @@ void worker_init(void)
 
        wp->w_fp = NULL;                /* Mark not in use */
        wp->w_next = NULL;
+       wp->w_task = NONE;
        if (mutex_init(&wp->w_event_mutex, NULL) != 0)
                panic("failed to initialize mutex");
        if (cond_init(&wp->w_event, NULL) != 0)
@@ -397,8 +398,8 @@ void worker_stop(struct worker_thread *worker)
        /* This thread is communicating with a driver or file server */
        if (worker->w_drv_sendrec != NULL) {                    /* Driver */
                worker->w_drv_sendrec->m_type = EIO;
-       } else if (worker->w_fs_sendrec != NULL) {              /* FS */
-               worker->w_fs_sendrec->m_type = EIO;
+       } else if (worker->w_sendrec != NULL) {         /* FS */
+               worker->w_sendrec->m_type = EIO;
        } else {
                panic("reply storage consistency error");       /* Oh dear */
        }
index 2f1ea32fecdf705067bda809b8e505a6e3bb1649..3ba55bdeb14d5e926fffbfe656833055ab611e00 100644 (file)
@@ -46,7 +46,7 @@ static phys_bytes alloc_pages(int pages, int flags);
 #if SANITYCHECKS
 struct {
        int used;
-       char *file;
+       const char *file;
        int line;
 } pagemap[NUMBER_PHYSICAL_PAGES];
 #endif
@@ -335,7 +335,7 @@ void mem_init(struct memory *chunks)
 }
 
 #if SANITYCHECKS
-void mem_sanitycheck(char *file, int line)
+void mem_sanitycheck(const char *file, int line)
 {
        int i;
        for(i = 0; i < NUMBER_PHYSICAL_PAGES; i++) {
@@ -506,7 +506,7 @@ void usedpages_reset(void)
 /*===========================================================================*
  *                             usedpages_add                                *
  *===========================================================================*/
-int usedpages_add_f(phys_bytes addr, phys_bytes len, char *file, int line)
+int usedpages_add_f(phys_bytes addr, phys_bytes len, const char *file, int line)
 {
        u32_t pagestart, pages;
 
@@ -525,7 +525,6 @@ int usedpages_add_f(phys_bytes addr, phys_bytes len, char *file, int line)
                assert(pagestart > 0);
                assert(pagestart < NUMBER_PHYSICAL_PAGES);
                thisaddr = pagestart * VM_PAGE_SIZE;
-               assert(pagestart >= 0);
                assert(pagestart < NUMBER_PHYSICAL_PAGES);
                if(pagemap[pagestart].used) {
                        static int warnings = 0;
index ea829d7a6f68368af35fc491ae8fa5d83c7c0cce..a62a7d49091170cc04941e499202b1ef58eb3848 100644 (file)
@@ -111,13 +111,13 @@ int do_willexit(message *msg)
        return OK;
 }
 
-int do_procctl(message *msg)
+int do_procctl(message *msg, int transid)
 {
        endpoint_t proc;
        struct vmproc *vmp;
 
        if(vm_isokendpt(msg->VMPCTL_WHO, &proc) != OK) {
-               printf("VM: bogus endpoint VM_PROCCTL %d\n",
+               printf("VM: bogus endpoint VM_PROCCTL %ld\n",
                        msg->VMPCTL_WHO);
                return EINVAL;
        }
@@ -133,11 +133,21 @@ int do_procctl(message *msg)
                                panic("VMPPARAM_CLEAR: pt_new failed");
                        pt_bind(&vmp->vm_pt, vmp);
                        return OK;
+               case VMPPARAM_HANDLEMEM:
+               {
+                       if(msg->m_source != VFS_PROC_NR)
+                               return EPERM;
+
+                        handle_memory_start(vmp, msg->VMPCTL_M1,
+                               msg->VMPCTL_LEN, msg->VMPCTL_FLAGS,
+                                VFS_PROC_NR, VFS_PROC_NR, transid, 1);
+
+                       return SUSPEND;
+               }
                default:
                        return EINVAL;
        }
 
-
        return OK;
 }
 
index 50d9ea4bdba946aa5997970fb974f23009aac48a..806fe38a96c0c1ab33b7baba98e657ed7f66fa28 100644 (file)
@@ -101,10 +101,10 @@ int do_fork(message *msg)
         * and its return value needn't be checked.
         */
        vir = msgaddr;
-       if (handle_memory(vmc, vir, sizeof(message), 1, NULL, 0, 0) != OK)
+       if (handle_memory_once(vmc, vir, sizeof(message), 1) != OK)
            panic("do_fork: handle_memory for child failed\n");
        vir = msgaddr;
-       if (handle_memory(vmp, vir, sizeof(message), 1, NULL, 0, 0) != OK)
+       if (handle_memory_once(vmp, vir, sizeof(message), 1) != OK)
            panic("do_fork: handle_memory for parent failed\n");
   }
 
index 880aca9349611907f79e68ea484b2a280d2195b8..d4c1e71b18f0f069acdee6ffeff9b588a0dd04dc 100644 (file)
@@ -25,7 +25,7 @@ EXTERN kinfo_t kernel_boot_info;
 EXTERN int nocheck;
 EXTERN int incheck;
 EXTERN int sc_lastline;
-EXTERN char *sc_lastfile;
+EXTERN const char *sc_lastfile;
 #endif
 
 extern struct minix_kerninfo *_minix_kerninfo;
index 9a926e0271e9866af9f6571abde4c49b7550d7ca..8fbb769d21794ed59141ac85a791b758ae83a9ed 100644 (file)
@@ -15,6 +15,7 @@
 #include <minix/const.h>
 #include <minix/bitmap.h>
 #include <minix/rs.h>
+#include <minix/vfsif.h>
 
 #include <sys/exec.h>
 
@@ -90,7 +91,8 @@ int main(void)
   /* This is VM's main loop. */
   while (TRUE) {
        int r, c;
-       int type, param;
+       int type;
+       int transid = 0;        /* VFS transid if any */
 
        SANITYCHECK(SCL_TOP);
        if(missing_spares > 0) {
@@ -109,13 +111,22 @@ int main(void)
        if(vm_isokendpt(who_e, &caller_slot) != OK)
                panic("invalid caller %d", who_e);
 
-       type = param = msg.m_type;
-       type &= 0x0000FFFF;
-       param >>= 16;
+       /* We depend on this being false for the initialized value. */
+       assert(!IS_VFS_FS_TRANSID(transid));
+
+       type = msg.m_type;
        c = CALLNUMBER(type);
        result = ENOSYS; /* Out of range or restricted calls return this. */
-       
-       if(msg.m_type == RS_INIT && msg.m_source == RS_PROC_NR) {
+
+       transid = TRNS_GET_ID(msg.m_type);
+
+       if((msg.m_source == VFS_PROC_NR) && IS_VFS_FS_TRANSID(transid)) {
+               /* If it's a request from VFS, it might have a transaction id. */
+               msg.m_type = TRNS_DEL_ID(msg.m_type);
+
+               /* Calls that use the transid */
+               result = do_procctl(&msg, transid);
+       } else if(msg.m_type == RS_INIT && msg.m_source == RS_PROC_NR) {
                result = do_rs_init(&msg);
        } else if (msg.m_type == VM_PAGEFAULT) {
                if (!IPC_STATUS_FLAGS_TEST(rcv_sts, IPC_FLG_MSG_FROM_KERNEL)) {
@@ -147,6 +158,9 @@ int main(void)
         */
        if(result != SUSPEND) {
                msg.m_type = result;
+
+               assert(!IS_VFS_FS_TRANSID(transid));
+
                if((r=ipc_send(who_e, &msg)) != OK) {
                        printf("VM: couldn't send %d to %d (err %d)\n",
                                msg.m_type, who_e, r);
@@ -223,7 +237,7 @@ static int libexec_copy_physcopy(struct exec_info *execi,
        end = ei->ip->start_addr + ei->ip->len;
        assert(ei->ip->start_addr + off + len <= end);
        return sys_physcopy(NONE, ei->ip->start_addr + off,
-               execi->proc_e, vaddr, len);
+               execi->proc_e, vaddr, len, 0);
 }
 
 static void boot_alloc(struct exec_info *execi, off_t vaddr,
@@ -279,7 +293,7 @@ static void exec_bootproc(struct vmproc *vmp, struct boot_image *ip)
                panic("VM: pt_bind failed");
 
        if(sys_physcopy(NONE, ip->start_addr, SELF,
-               (vir_bytes) hdr, sizeof(hdr)) != OK)
+               (vir_bytes) hdr, sizeof(hdr), 0) != OK)
                panic("can't look at boot proc header");
 
        execi->stack_high = kernel_boot_info.user_sp;
@@ -320,7 +334,7 @@ static void exec_bootproc(struct vmproc *vmp, struct boot_image *ip)
        minix_stack_fill(path, argc, argv, envc, envp, frame_size, frame, &vsp,
                &psp);
 
-       if(handle_memory(vmp, vsp, frame_size, 1, NULL, NULL, 0) != OK)
+       if(handle_memory_once(vmp, vsp, frame_size, 1) != OK)
                panic("vm: could not map stack for boot process %s (ep=%d)\n",
                        execi->progname, vmp->vm_endpoint);
 
@@ -338,6 +352,15 @@ static void exec_bootproc(struct vmproc *vmp, struct boot_image *ip)
                panic("VMCTL_BOOTINHIBIT_CLEAR failed");
 }
 
+static int do_procctl_notrans(message *msg)
+{
+       int transid = 0;
+
+       assert(!IS_VFS_FS_TRANSID(transid));
+
+       return do_procctl(msg, transid);
+}
+
 void init_vm(void)
 {
        int s, i;
@@ -459,6 +482,8 @@ void init_vm(void)
        CALLMAP(VM_WILLEXIT, do_willexit);
        CALLMAP(VM_NOTIFY_SIG, do_notify_sig);
 
+       CALLMAP(VM_PROCCTL, do_procctl_notrans);
+
        /* Calls from VFS. */
        CALLMAP(VM_VFS_REPLY, do_vfs_reply);
        CALLMAP(VM_VFS_MMAP, do_vfs_mmap);
@@ -468,9 +493,6 @@ void init_vm(void)
        CALLMAP(VM_RS_UPDATE, do_rs_update);
        CALLMAP(VM_RS_MEMCTL, do_rs_memctl);
 
-       /* Calls from RS/VFS */
-       CALLMAP(VM_PROCCTL, do_procctl);
-
        /* Generic calls. */
        CALLMAP(VM_REMAP, do_remap);
        CALLMAP(VM_REMAP_RO, do_remap);
index 68a7813e9da1071a7a1ebb857fd498caad362e7a..172e30ed92ed715f794129752e8bfc00f43a8526 100644 (file)
@@ -24,7 +24,7 @@ static int anon_unreference(struct phys_region *pr);
 static int anon_pagefault(struct vmproc *vmp, struct vir_region *region, 
        struct phys_region *ph, int write, vfs_callback_t cb, void *state,
        int len, int *io);
-static int anon_sanitycheck(struct phys_region *pr, char *file, int line);
+static int anon_sanitycheck(struct phys_region *pr, const char *file, int line);
 static int anon_writable(struct phys_region *pr);
 static int anon_resize(struct vmproc *vmp, struct vir_region *vr, vir_bytes l);
 static u32_t anon_regionid(struct vir_region *region);
@@ -87,8 +87,7 @@ static int anon_pagefault(struct vmproc *vmp, struct vir_region *region,
        }
 
        if(ph->ph->refcount < 2 || !write) {
-               printf("anon_pagefault: %d refcount, %d write - not handling pagefault\n",
-                       ph->ph->refcount, write);
+               /* memory is ready already */
                return OK;
        }       
 
@@ -97,7 +96,7 @@ static int anon_pagefault(struct vmproc *vmp, struct vir_region *region,
        return mem_cow(region, ph, new_page_cl, new_page);
 }
 
-static int anon_sanitycheck(struct phys_region *pr, char *file, int line)
+static int anon_sanitycheck(struct phys_region *pr, const char *file, int line)
 {
        MYASSERT(usedpages_add(pr->ph->phys, VM_PAGE_SIZE) == OK);
        return OK;
index 4b09ec52f1f67cbb2d4e7064dc8696d740c7493f..d2f063df14a99cb64b3e0d0ebe5b40c12ce23999 100644 (file)
@@ -13,7 +13,7 @@ static int anon_contig_unreference(struct phys_region *pr);
 static int anon_contig_pagefault(struct vmproc *vmp, struct vir_region *region, 
        struct phys_region *ph, int write, vfs_callback_t cb, void *state,
        int len, int *io);
-static int anon_contig_sanitycheck(struct phys_region *pr, char *file, int line);
+static int anon_contig_sanitycheck(struct phys_region *pr, const char *file, int line);
 static int anon_contig_writable(struct phys_region *pr);
 static int anon_contig_resize(struct vmproc *vmp, struct vir_region *vr, vir_bytes l);
 static int anon_contig_new(struct vir_region *vr);
@@ -111,7 +111,7 @@ static int anon_contig_unreference(struct phys_region *pr)
        return mem_type_anon.ev_unreference(pr);
 }
 
-static int anon_contig_sanitycheck(struct phys_region *pr, char *file, int line)
+static int anon_contig_sanitycheck(struct phys_region *pr, const char *file, int line)
 {
        return mem_type_anon.ev_sanitycheck(pr, file, line);
 }
index 7c501cf52da8470f5761a3a3406825ba3dca0551..b61ac939eb2c26aeba265ebf50bdd39c849c5502 100644 (file)
@@ -27,7 +27,7 @@
 
 static int cache_reference(struct phys_region *pr, struct phys_region *pr2);
 static int cache_unreference(struct phys_region *pr);
-static int cache_sanitycheck(struct phys_region *pr, char *file, int line);
+static int cache_sanitycheck(struct phys_region *pr, const char *file, int line);
 static int cache_writable(struct phys_region *pr);
 static int cache_resize(struct vmproc *vmp, struct vir_region *vr, vir_bytes l);
 static int cache_pagefault(struct vmproc *vmp, struct vir_region *region, 
@@ -65,7 +65,7 @@ static int cache_unreference(struct phys_region *pr)
        return mem_type_anon.ev_unreference(pr);
 }
 
-static int cache_sanitycheck(struct phys_region *pr, char *file, int line)
+static int cache_sanitycheck(struct phys_region *pr, const char *file, int line)
 {
        MYASSERT(usedpages_add(pr->ph->phys, VM_PAGE_SIZE) == OK);
        return OK;
index 2588cdbea8ee6f5c6ab7f0466882169b9ff63cdf..ef25cff559dd6728941dff029c6004cccbc3fb4c 100644 (file)
@@ -20,7 +20,7 @@ static int mappedfile_unreference(struct phys_region *pr);
 static int mappedfile_pagefault(struct vmproc *vmp, struct vir_region *region, 
        struct phys_region *ph, int write, vfs_callback_t callback, void *state,
        int len, int *io);
-static int mappedfile_sanitycheck(struct phys_region *pr, char *file, int line);
+static int mappedfile_sanitycheck(struct phys_region *pr, const char *file, int line);
 static int mappedfile_writable(struct phys_region *pr);
 static int mappedfile_copy(struct vir_region *vr, struct vir_region *newvr);
 static int mappedfile_lowshrink(struct vir_region *vr, vir_bytes len);
@@ -124,7 +124,9 @@ static int mappedfile_pagefault(struct vmproc *vmp, struct vir_region *region,
                }
 
                if(!cb) {
+#if 0
                        printf("VM: mem_file: no callback, returning EFAULT\n");
+#endif
                        sys_diagctl_stacktrace(vmp->vm_endpoint);
                        return EFAULT;
                }
@@ -139,14 +141,16 @@ static int mappedfile_pagefault(struct vmproc *vmp, struct vir_region *region,
        }
 
        if(!write) {
+#if 0
                printf("mappedfile_pagefault: nonwrite fault?\n");
-               return EFAULT;
+#endif
+               return OK;
        }
 
        return cow_block(vmp, region, ph, 0);
 }
 
-static int mappedfile_sanitycheck(struct phys_region *pr, char *file, int line)
+static int mappedfile_sanitycheck(struct phys_region *pr, const char *file, int line)
 {
        MYASSERT(usedpages_add(pr->ph->phys, VM_PAGE_SIZE) == OK);
        return OK;
index 19239b09fb71a1074f8ba057675630e8ffc6402e..d51029111f41fde1393be14c3e57837cd1c4d32b 100644 (file)
@@ -17,7 +17,7 @@ static int shared_unreference(struct phys_region *pr);
 static int shared_pagefault(struct vmproc *vmp, struct vir_region *region, 
        struct phys_region *ph, int write, vfs_callback_t cb, void *state,
        int len, int *io);
-static int shared_sanitycheck(struct phys_region *pr, char *file, int line);
+static int shared_sanitycheck(struct phys_region *pr, const char *file, int line);
 static int shared_writable(struct phys_region *pr);
 static void shared_delete(struct vir_region *region);
 static u32_t shared_regionid(struct vir_region *region);
@@ -149,7 +149,7 @@ static int shared_pagefault(struct vmproc *vmp, struct vir_region *region,
        return OK;
 }
 
-static int shared_sanitycheck(struct phys_region *pr, char *file, int line)
+static int shared_sanitycheck(struct phys_region *pr, const char *file, int line)
 {
        return OK;
 }
index a8c14dce9bc248d882bbd71d440abf3f305efaf2..a7edaa3a50baae62d810dba1f7862a9745ce1202 100644 (file)
@@ -22,7 +22,7 @@ typedef struct mem_type {
        void (*ev_split)(struct vmproc *vmp, struct vir_region *vr,
                struct vir_region *r1, struct vir_region *r2);
        int (*writable)(struct phys_region *pr);
-       int (*ev_sanitycheck)(struct phys_region *pr, char *file, int line);
+       int (*ev_sanitycheck)(struct phys_region *pr, const char *file, int line);
         int (*ev_copy)(struct vir_region *vr, struct vir_region *newvr);
         int (*ev_lowshrink)(struct vir_region *vr, vir_bytes len);
        u32_t (*regionid)(struct vir_region *vr);
index 95e1142cc0cd3ec117d5b84fd175fc187ca8bf7f..ed1f0a4760784a9535cd0e144ede95e7223a27e5 100644 (file)
@@ -14,6 +14,9 @@
 #include <minix/syslib.h>
 #include <minix/safecopies.h>
 #include <minix/bitmap.h>
+#include <minix/vfsif.h>
+
+#include <machine/vmparam.h>
 
 #include <errno.h>
 #include <string.h>
 #include "util.h"
 #include "region.h"
 
+struct pf_state {
+        endpoint_t ep;
+        vir_bytes vaddr;
+       u32_t err;
+};
+
+struct hm_state {
+       endpoint_t caller;      /* KERNEL or process? if NONE, no callback */
+       endpoint_t requestor;   /* on behalf of whom? */
+       int transid;            /* VFS transaction id if valid */
+       struct vmproc *vmp;     /* target address space */
+       vir_bytes mem, len;     /* memory range */
+       int wrflag;             /* must it be writable or not */
+       int valid;              /* sanity check */
+       int vfs_avail;          /* may vfs be called to satisfy this range? */
+#define VALID  0xc0ff1
+};
+
+static void handle_memory_continue(struct vmproc *vmp, message *m,
+        void *arg, void *statearg);
+static int handle_memory_step(struct hm_state *hmstate);
+static void handle_memory_final(struct hm_state *state, int result);
+
 /*===========================================================================*
  *                             pf_errstr                               *
  *===========================================================================*/
@@ -44,23 +70,9 @@ char *pf_errstr(u32_t err)
        return buf;
 }
 
-struct pf_state {
-        endpoint_t ep;
-        vir_bytes vaddr;
-       u32_t err;
-};
-
-struct hm_state {
-       endpoint_t requestor;
-       struct vmproc *vmp;
-       vir_bytes mem;
-       vir_bytes len;
-       int wrflag;
-};
-
 static void pf_cont(struct vmproc *vmp, message *m, void *arg, void *statearg);
 
-static void hm_cont(struct vmproc *vmp, message *m, void *arg, void *statearg);
+static void handle_memory_continue(struct vmproc *vmp, message *m, void *arg, void *statearg);
 
 static void handle_pagefault(endpoint_t ep, vir_bytes addr, u32_t err, int retry)
 {
@@ -156,25 +168,65 @@ static void pf_cont(struct vmproc *vmp, message *m,
        handle_pagefault(state->ep, state->vaddr, state->err, 1);
 }
 
-static void hm_cont(struct vmproc *vmp, message *m,
+static void handle_memory_continue(struct vmproc *vmp, message *m,
         void *arg, void *statearg)
 {
        int r;
        struct hm_state *state = statearg;
-       printf("hm_cont: result %d\n", m->VMV_RESULT);
-       r = handle_memory(vmp, state->mem, state->len, state->wrflag,
-               hm_cont, &state, sizeof(state));
+       assert(state);
+       assert(state->caller != NONE);
+       assert(state->valid == VALID);
+
+       if(m->VMV_RESULT != OK) {
+               printf("VM: handle_memory_continue: vfs request failed\n");
+               handle_memory_final(state, m->VMV_RESULT);
+               return;
+       }
+
+       r = handle_memory_step(state);
+
+       assert(state->valid == VALID);
+
        if(r == SUSPEND) {
-               printf("VM: hm_cont: damnit: hm_cont: more SUSPEND\n");
                return;
        }
 
-       printf("VM: hm_cont: ok, result %d, requestor %d\n", r, state->requestor);
+       assert(state->valid == VALID);
+
+       handle_memory_final(state, r);
+}
+
+static void handle_memory_final(struct hm_state *state, int result)
+{
+       int r;
+
+       assert(state);
+       assert(state->valid == VALID);
+
+       if(state->caller == KERNEL) {
+               if((r=sys_vmctl(state->requestor, VMCTL_MEMREQ_REPLY, result)) != OK)
+                       panic("handle_memory_continue: sys_vmctl failed: %d", r);
+       } else if(state->caller != NONE) {
+               /* Send a reply msg */
+               message msg;
+               memset(&msg, 0, sizeof(msg));
+               msg.m_type = result;
+
+               if(IS_VFS_FS_TRANSID(state->transid)) {
+                       assert(state->caller == VFS_PROC_NR);
+                       /* If a transaction ID was set, reset it */
+                       msg.m_type = TRNS_ADD_ID(msg.m_type, state->transid);
+               }
+
+               if(asynsend3(state->caller, &msg, 0) != OK) {
+                       panic("handle_memory_final: asynsend3 failed");
+               }
 
-       if(sys_vmctl(state->requestor, VMCTL_MEMREQ_REPLY, r) != OK)
-               panic("hm_cont: sys_vmctl failed: %d", r);
+               assert(state->valid == VALID);
 
-       printf("MEMREQ_REPLY sent\n");
+               /* fail fast if anyone tries to access this state again */
+               memset(state, 0, sizeof(*state));
+       }
 }
 
 /*===========================================================================*
@@ -185,6 +237,52 @@ void do_pagefaults(message *m)
        handle_pagefault(m->m_source, m->VPF_ADDR, m->VPF_FLAGS, 0);
 }
 
+int handle_memory_once(struct vmproc *vmp, vir_bytes mem, vir_bytes len,
+       int wrflag)
+{
+       int r;
+       r = handle_memory_start(vmp, mem, len, wrflag, NONE, NONE, 0, 0);
+       assert(r != SUSPEND);
+       return r;
+}
+
+int handle_memory_start(struct vmproc *vmp, vir_bytes mem, vir_bytes len,
+       int wrflag, endpoint_t caller, endpoint_t requestor, int transid,
+       int vfs_avail)
+{
+       int r;
+       struct hm_state state;
+       vir_bytes o;
+
+       if((o = mem % PAGE_SIZE)) {
+               mem -= o;
+               len += o;
+       }
+
+       len = roundup(len, PAGE_SIZE);
+
+       state.vmp = vmp;
+       state.mem = mem;
+       state.len = len;
+       state.wrflag = wrflag;
+       state.requestor = requestor;
+       state.caller = caller;
+       state.transid = transid;
+       state.valid = VALID;
+       state.vfs_avail = vfs_avail;
+
+       r = handle_memory_step(&state);
+
+       if(r == SUSPEND) {
+               assert(caller != NONE);
+               assert(vfs_avail);
+       } else {
+               handle_memory_final(&state, r);
+       }
+
+       return r;
+}
+
 /*===========================================================================*
  *                                do_memory                                 *
  *===========================================================================*/
@@ -205,21 +303,21 @@ void do_memory(void)
                switch(r) {
                case VMPTYPE_CHECK:
                {
-                       struct hm_state state;
+                       int transid = 0;
+                       int vfs_avail;
 
                        if(vm_isokendpt(who, &p) != OK)
                                panic("do_memory: bad endpoint: %d", who);
                        vmp = &vmproc[p];
 
+                       assert(!IS_VFS_FS_TRANSID(transid));
 
-                       state.vmp = vmp;
-                       state.mem = mem;
-                       state.len = len;
-                       state.wrflag = wrflag;
-                       state.requestor = requestor;
+                       /* is VFS blocked? */
+                       if(requestor == VFS_PROC_NR) vfs_avail = 0;
+                       else vfs_avail = 1;
 
-                       r = handle_memory(vmp, mem, len,
-                               wrflag, hm_cont, &state, sizeof(state));
+                       handle_memory_start(vmp, mem, len, wrflag,
+                               KERNEL, requestor, transid, vfs_avail);
 
                        break;
                }
@@ -227,69 +325,56 @@ void do_memory(void)
                default:
                        return;
                }
-
-               if(r != SUSPEND) {
-                  if(sys_vmctl(requestor, VMCTL_MEMREQ_REPLY, r) != OK)
-                       panic("do_memory: sys_vmctl failed: %d", r);
-               }
        }
 }
 
-int handle_memory(struct vmproc *vmp, vir_bytes mem, vir_bytes len, int wrflag,
-       vfs_callback_t callback, void *state, int statelen)
+static int handle_memory_step(struct hm_state *hmstate)
 {
        struct vir_region *region;
-       vir_bytes o;
-       struct hm_state *hmstate = (struct hm_state *) state;
 
        /* Page-align memory and length. */
-       o = mem % VM_PAGE_SIZE;
-       mem -= o;
-       len += o;
-       o = len % VM_PAGE_SIZE;
-       if(o > 0) len += VM_PAGE_SIZE - o;
+       assert(hmstate);
+       assert(hmstate->valid == VALID);
+       assert(!(hmstate->mem % VM_PAGE_SIZE));
+       assert(!(hmstate->len % VM_PAGE_SIZE));
 
-       while(len > 0) {
+       while(hmstate->len > 0) {
                int r;
-               if(!(region = map_lookup(vmp, mem, NULL))) {
+               if(!(region = map_lookup(hmstate->vmp, hmstate->mem, NULL))) {
 #if VERBOSE
-                       map_printmap(vmp);
+                       map_printmap(hmstate->vmp);
                        printf("VM: do_memory: memory doesn't exist\n");
 #endif
-                       r = EFAULT;
-               } else if(!(region->flags & VR_WRITABLE) && wrflag) {
+                       return EFAULT;
+               } else if(!(region->flags & VR_WRITABLE) && hmstate->wrflag) {
 #if VERBOSE
                        printf("VM: do_memory: write to unwritable map\n");
 #endif
-                       r = EFAULT;
+                       return EFAULT;
                } else {
                        vir_bytes offset, sublen;
-                       assert(region->vaddr <= mem);
+                       assert(region->vaddr <= hmstate->mem);
                        assert(!(region->vaddr % VM_PAGE_SIZE));
-                       offset = mem - region->vaddr;
-                       sublen = len;
+                       offset = hmstate->mem - region->vaddr;
+                       sublen = hmstate->len;
                        if(offset + sublen > region->length)
                                sublen = region->length - offset;
        
-                       if(hmstate && hmstate->requestor == VFS_PROC_NR
-                          && region->def_memtype == &mem_type_mappedfile) {
-                               r = map_handle_memory(vmp, region, offset,
-                                  sublen, wrflag, NULL, NULL, 0);
+                       if((region->def_memtype == &mem_type_mappedfile &&
+                         !hmstate->vfs_avail) || hmstate->caller == NONE) {
+                               r = map_handle_memory(hmstate->vmp, region, offset,
+                                  sublen, hmstate->wrflag, NULL, NULL, 0);
+                               assert(r != SUSPEND);
                        } else {
-                               r = map_handle_memory(vmp, region, offset,
-                                  sublen, wrflag, callback, state, sizeof(state));
+                               r = map_handle_memory(hmstate->vmp, region, offset,
+                                  sublen, hmstate->wrflag, handle_memory_continue,
+                                       hmstate, sizeof(*hmstate));
                        }
 
-                       len -= sublen;
-                       mem += sublen;
-               }
-       
-               if(r != OK) {
-#if VERBOSE
-                       printf("VM: memory range 0x%lx-0x%lx not available in %d\n",
-                               mem, mem+len, vmp->vm_endpoint);
-#endif
-                       return r;
+                       if(r != OK) return r;
+
+                       hmstate->len -= sublen;
+                       hmstate->mem += sublen;
                }
        }
 
index 4892496261b363d312296fa2179a929c5dcb796c..e0fe60af2759a5be16c0a8cb01afcf16590ef7fd 100644 (file)
@@ -65,12 +65,15 @@ struct vmproc *vmprocess = &vmproc[VM_PROC_NR];
 # define SPAREPAGES 150
 # define STATIC_SPAREPAGES 140 
 #else
-static u32_t global_bit = 0;
 # define SPAREPAGES 20
 # define STATIC_SPAREPAGES 15 
 #endif /* __arm__ */
 #endif
 
+#ifdef __i386__
+static u32_t global_bit = 0;
+#endif
+
 #define SPAREPAGEDIRS 1
 #define STATIC_SPAREPAGEDIRS 1
 
@@ -115,7 +118,7 @@ static char static_sparepagedirs[ARCH_PAGEDIR_SIZE*STATIC_SPAREPAGEDIRS + ARCH_P
 /*===========================================================================*
  *                             pt_sanitycheck                               *
  *===========================================================================*/
-void pt_sanitycheck(pt_t *pt, char *file, int line)
+void pt_sanitycheck(pt_t *pt, const char *file, int line)
 {
 /* Basic pt sanity check. */
        int slot;
@@ -1234,10 +1237,10 @@ void pt_init(void)
                panic("VM: sys_vmctl_get_pdbr failed");
 #if defined(__i386__)
        if(sys_vircopy(NONE, mypdbr, SELF,
-               (vir_bytes) currentpagedir, VM_PAGE_SIZE) != OK)
+               (vir_bytes) currentpagedir, VM_PAGE_SIZE, 0) != OK)
 #elif defined(__arm__)
        if(sys_vircopy(NONE, myttbr, SELF,
-               (vir_bytes) currentpagedir, ARCH_PAGEDIR_SIZE) != OK)
+               (vir_bytes) currentpagedir, ARCH_PAGEDIR_SIZE, 0) != OK)
 #endif
                panic("VM: sys_vircopy failed");
 
index 869bfc8a9fd532516017805445c75ea16ccbee58..0ad9998cf250c93a5d9c79b58f38ef41bda7e4ad 100644 (file)
@@ -28,12 +28,12 @@ void *reservedqueue_new(int, int, int, int);
 int reservedqueue_alloc(void *, phys_bytes *, void **);
 void reservedqueue_add(void *, void *, phys_bytes);
 void alloc_cycle(void);
-void mem_sanitycheck(char *file, int line);
+void mem_sanitycheck(const char *file, int line);
 phys_clicks alloc_mem(phys_clicks clicks, u32_t flags);
 void memstats(int *nodes, int *pages, int *largest);
 void printmemstats(void);
 void usedpages_reset(void);
-int usedpages_add_f(phys_bytes phys, phys_bytes len, char *file, int
+int usedpages_add_f(phys_bytes phys, phys_bytes len, const char *file, int
        line);
 void free_mem(phys_clicks base, phys_clicks clicks);
 void mem_add_total_pages(int pages);
@@ -54,7 +54,7 @@ int do_getrusage(message *m);
 void clear_proc(struct vmproc *vmp);
 int do_exit(message *msg);
 int do_willexit(message *msg);
-int do_procctl(message *msg);
+int do_procctl(message *msg, int transid);
 void free_proc(struct vmproc *vmp);
 
 /* fork.c */
@@ -84,8 +84,11 @@ int do_vfs_mmap(message *m);
 void do_pagefaults(message *m);
 void do_memory(void);
 char *pf_errstr(u32_t err);
-int handle_memory(struct vmproc *vmp, vir_bytes mem, vir_bytes len, int
-       wrflag, vfs_callback_t cb, void *state, int statelen);
+int handle_memory_start(struct vmproc *vmp, vir_bytes mem, vir_bytes len,
+       int wrflag, endpoint_t caller, endpoint_t requestor, int transid,
+       int vfs_avail);
+int handle_memory_once(struct vmproc *vmp, vir_bytes mem, vir_bytes len,
+       int wrflag);
 
 /* $(ARCH)/pagetable.c */
 void pt_init(void);
@@ -115,21 +118,21 @@ int get_vm_self_pages(void);
 int pt_writable(struct vmproc *vmp, vir_bytes v);
 
 #if SANITYCHECKS
-void pt_sanitycheck(pt_t *pt, char *file, int line);
+void pt_sanitycheck(pt_t *pt, const char *file, int line);
 #endif
 
 /* slaballoc.c */
 void *slaballoc(int bytes);
 void slabfree(void *mem, int bytes);
 void slabstats(void);
-void slab_sanitycheck(char *file, int line);
+void slab_sanitycheck(const char *file, int line);
 #define SLABALLOC(var) (var = slaballoc(sizeof(*var)))
 #define SLABFREE(ptr) do { slabfree(ptr, sizeof(*(ptr))); (ptr) = NULL; } while(0)
 #if SANITYCHECKS
 
 void slabunlock(void *mem, int bytes);
 void slablock(void *mem, int bytes);
-int slabsane_f(char *file, int line, void *mem, int bytes);
+int slabsane_f(const char *file, int line, void *mem, int bytes);
 #endif
 
 /* region.c */
@@ -184,7 +187,7 @@ int get_region_info(struct vmproc *vmp, struct vm_region_info *vri, int
 int copy_abs2region(phys_bytes abs, struct vir_region *destregion,
        phys_bytes offset, phys_bytes len);
 #if SANITYCHECKS
-void map_sanitycheck(char *file, int line);
+void map_sanitycheck(const char *file, int line);
 #endif
 
 /* rs.c */
index 7450fd844d496a704dec30af380bf0b36f488bbb..507407d6736291f770c98741dbb30c21d4132594 100644 (file)
@@ -165,7 +165,7 @@ static int map_sanitycheck_pt(struct vmproc *vmp,
 /*===========================================================================*
  *                             map_sanitycheck                      *
  *===========================================================================*/
-void map_sanitycheck(char *file, int line)
+void map_sanitycheck(const char *file, int line)
 {
        struct vmproc *vmp;
 
@@ -723,7 +723,9 @@ int map_pf(struct vmproc *vmp,
                }
 
                if(r != OK) {
+#if 0
                        printf("map_pf: pagefault in %s failed\n", ph->memtype->name);
+#endif
                        if(ph)
                                pb_unreferenced(region, ph, 1);
                        return r;
@@ -812,7 +814,7 @@ struct vir_region *map_copy_region(struct vmproc *vmp, struct vir_region *vr)
        struct phys_region *ph;
        int r;
 #if SANITYCHECKS
-       int cr;
+       unsigned int cr;
        cr = physregions(vr);
 #endif
        vir_bytes p;
index a2993ce5f15d461d4ed4c34e722dccd4fccd8aa9..f353d9b3acf03a8bdd91fac88d5f69feac156dfd 100644 (file)
@@ -16,7 +16,7 @@
         printf("VM:%s:%d: %s failed (last sanity check %s:%d)\n", file, line, #c, sc_lastfile, sc_lastline); \
        panic("sanity check failed"); } } while(0)
 
-#define SLABSANITYCHECK(l) if(_minix_kerninfo && 0) { \
+#define SLABSANITYCHECK(l) if(_minix_kerninfo) { \
        slab_sanitycheck(__FILE__, __LINE__); }
 
 #define SANITYCHECK(l) if(!nocheck && _minix_kerninfo && 0) {  \
index 61a7ff8495e238b07ec86ac413e23654ab691275..6b19e61f5bcc3c7d83dba53b445bc8f1ac2d66c7 100644 (file)
@@ -190,7 +190,7 @@ static struct slabdata *newslabdata(void)
 /*===========================================================================*
  *                             checklist                                    *
  *===========================================================================*/
-static int checklist(char *file, int line,
+static int checklist(const char *file, int line,
        struct slabheader *s, int bytes)
 {
        struct slabdata *n = s->list_head;
@@ -225,7 +225,7 @@ static int checklist(char *file, int line,
 /*===========================================================================*
  *                             void slab_sanitycheck                        *
  *===========================================================================*/
-void slab_sanitycheck(char *file, int line)
+void slab_sanitycheck(const char *file, int line)
 {
        int s;
        for(s = 0; s < SLABSIZES; s++) {
@@ -236,7 +236,7 @@ void slab_sanitycheck(char *file, int line)
 /*===========================================================================*
  *                             int slabsane                                 *
  *===========================================================================*/
-int slabsane_f(char *file, int line, void *mem, int bytes)
+int slabsane_f(const char *file, int line, void *mem, int bytes)
 {
        struct slabheader *s;
        struct slabdata *f;
index c59462d49d718f979d88b192e605234be9cb94e3..aa00c95badac6416b6218d6c2c44ff4b95a0159f 100644 (file)
@@ -170,7 +170,7 @@ int do_info(message *m)
         * deadlock. Note that no memory mapping can be undone without the
         * involvement of VM, so we are safe until we're done.
         */
-       r = handle_memory(vmp, ptr, size, 1 /*wrflag*/, NULL, NULL, 0);
+       r = handle_memory_once(vmp, ptr, size, 1 /*wrflag*/);
        if (r != OK) return r;
 
        /* Now that we know the copy out will succeed, perform the actual copy