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