1 2 /* Sending requests to VFS and handling the replies. */ 3 4 #define _SYSTEM 1 5 6 #include <minix/callnr.h> 7 #include <minix/com.h> 8 #include <minix/config.h> 9 #include <minix/const.h> 10 #include <minix/ds.h> 11 #include <minix/endpoint.h> 12 #include <minix/minlib.h> 13 #include <minix/type.h> 14 #include <minix/ipc.h> 15 #include <minix/sysutil.h> 16 #include <minix/syslib.h> 17 #include <minix/type.h> 18 #include <minix/bitmap.h> 19 #include <string.h> 20 #include <errno.h> 21 #include <env.h> 22 #include <unistd.h> 23 #include <assert.h> 24 #include <sys/param.h> 25 26 #include "proto.h" 27 #include "glo.h" 28 #include "util.h" 29 #include "region.h" 30 #include "sanitycheck.h" 31 32 #define STATELEN 70 33 34 static struct vfs_request_node { 35 message reqmsg; 36 char reqstate[STATELEN]; 37 void *opaque; 38 endpoint_t who; 39 int req_id; 40 vfs_callback_t callback; 41 struct vfs_request_node *next; 42 } *first_queued, *active; 43 44 static void activate(void) 45 { 46 assert(!active); 47 assert(first_queued); 48 49 active = first_queued; 50 first_queued = first_queued->next; 51 52 if(asynsend3(VFS_PROC_NR, &active->reqmsg, AMF_NOREPLY) != OK) 53 panic("VM: asynsend to VFS failed"); 54 } 55 56 #define ID_MAX LONG_MAX 57 58 /*===========================================================================* 59 * vfs_request * 60 *===========================================================================*/ 61 int vfs_request(int reqno, int fd, struct vmproc *vmp, u64_t offset, u32_t len, 62 vfs_callback_t reply_callback, void *cbarg, void *state, int statelen) 63 { 64 /* Perform an asynchronous request to VFS. 65 * We send a message of type VFS_VMCALL to VFS. VFS will respond 66 * with message type VM_VFS_REPLY. We send the request asynchronously 67 * and then handle the reply as it if were a VM_VFS_REPLY request. 68 */ 69 message *m; 70 static int reqid = 0; 71 struct vfs_request_node *reqnode; 72 73 reqid++; 74 75 assert(statelen <= STATELEN); 76 77 if(!SLABALLOC(reqnode)) { 78 printf("vfs_request: no memory for request node\n"); 79 return ENOMEM; 80 } 81 82 m = &reqnode->reqmsg; 83 memset(m, 0, sizeof(*m)); 84 m->m_type = VFS_VMCALL; 85 m->VFS_VMCALL_REQ = reqno; 86 m->VFS_VMCALL_FD = fd; 87 m->VFS_VMCALL_REQID = reqid; 88 m->VFS_VMCALL_ENDPOINT = vmp->vm_endpoint; 89 m->VFS_VMCALL_OFFSET = offset; 90 m->VFS_VMCALL_LENGTH = len; 91 92 reqnode->who = vmp->vm_endpoint; 93 reqnode->req_id = reqid; 94 reqnode->next = first_queued; 95 reqnode->callback = reply_callback; 96 reqnode->opaque = cbarg; 97 if(state) memcpy(reqnode->reqstate, state, statelen); 98 first_queued = reqnode; 99 100 /* Send the request message if none pending. */ 101 if(!active) 102 activate(); 103 104 return OK; 105 } 106 107 /*===========================================================================* 108 * do_vfs_reply * 109 *===========================================================================*/ 110 int do_vfs_reply(message *m) 111 { 112 /* VFS has handled a VM request and VFS has replied. It must be the 113 * active request. 114 */ 115 struct vfs_request_node *orignode = active; 116 vfs_callback_t req_callback; 117 void *cbarg; 118 int n; 119 struct vmproc *vmp; 120 121 assert(active); 122 assert(active->req_id == m->VMV_REQID); 123 124 /* the endpoint may have exited */ 125 if(vm_isokendpt(m->VMV_ENDPOINT, &n) != OK) 126 vmp = NULL; 127 else vmp = &vmproc[n]; 128 129 req_callback = active->callback; 130 cbarg = active->opaque; 131 active = NULL; 132 133 /* Invoke requested reply-callback within VM. */ 134 if(req_callback) req_callback(vmp, m, cbarg, orignode->reqstate); 135 136 SLABFREE(orignode); 137 138 /* Send the next request message if any and not re-activated. */ 139 if(first_queued && !active) 140 activate(); 141 142 return SUSPEND; /* don't reply to the reply */ 143 } 144 145