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