xref: /minix/minix/servers/vm/vfs.c (revision 7f5f010b)
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