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