make vfs & filesystems use failable copying

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
This commit is contained in:
Ben Gras
2014-01-16 14:22:13 +01:00
committed by Lionel Sambuc
parent 8c277f99f4
commit 565f13088f
58 changed files with 705 additions and 296 deletions

View File

@@ -356,13 +356,12 @@
#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 CP_FLAG_TRY 0x01 /* do not transparently map */
#define UMAP_SEG m5_s1
/* 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) */
/* Field names for SYS_VUMAP. */
#define VUMAP_ENDPT m10_i1 /* grant owner, or SELF for local addresses */
#define VUMAP_VADDR m10_l1 /* address of virtual (input) vector */
@@ -476,7 +475,6 @@
/* 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 */
@@ -493,8 +491,6 @@
#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 */
@@ -936,10 +932,14 @@
/* 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)

View 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 */

View 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. */

View 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. */

View 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);