xref: /minix3/minix/servers/vfs/comm.c (revision e3b8d4bb58a799dc7fd563ac39bf3015762af03b)
1433d6423SLionel Sambuc #include "fs.h"
2433d6423SLionel Sambuc #include <minix/vfsif.h>
3433d6423SLionel Sambuc #include <assert.h>
4433d6423SLionel Sambuc #include <string.h>
5433d6423SLionel Sambuc 
6433d6423SLionel Sambuc static int sendmsg(struct vmnt *vmp, endpoint_t dst, struct worker_thread *wp);
7433d6423SLionel Sambuc static int queuemsg(struct vmnt *vmp);
8433d6423SLionel Sambuc 
9433d6423SLionel Sambuc /*===========================================================================*
10433d6423SLionel Sambuc  *				sendmsg					     *
11433d6423SLionel Sambuc  *===========================================================================*/
sendmsg(struct vmnt * vmp,endpoint_t dst,struct worker_thread * wp)12433d6423SLionel Sambuc static int sendmsg(struct vmnt *vmp, endpoint_t dst, struct worker_thread *wp)
13433d6423SLionel Sambuc {
14433d6423SLionel Sambuc /* This is the low level function that sends requests.
15433d6423SLionel Sambuc  * Currently to FSes or VM.
16433d6423SLionel Sambuc  */
17433d6423SLionel Sambuc   int r, transid;
18433d6423SLionel Sambuc 
19433d6423SLionel Sambuc   if(vmp) vmp->m_comm.c_cur_reqs++;	/* One more request awaiting a reply */
20433d6423SLionel Sambuc   transid = wp->w_tid + VFS_TRANSID;
21433d6423SLionel Sambuc   wp->w_sendrec->m_type = TRNS_ADD_ID(wp->w_sendrec->m_type, transid);
22433d6423SLionel Sambuc   wp->w_task = dst;
23433d6423SLionel Sambuc   if ((r = asynsend3(dst, wp->w_sendrec, AMF_NOREPLY)) != OK) {
24433d6423SLionel Sambuc 	printf("VFS: sendmsg: error sending message. "
25433d6423SLionel Sambuc 		"dest: %d req_nr: %d err: %d\n", dst,
26433d6423SLionel Sambuc 			wp->w_sendrec->m_type, r);
27433d6423SLionel Sambuc 	util_stacktrace();
28433d6423SLionel Sambuc 	return(r);
29433d6423SLionel Sambuc   }
30433d6423SLionel Sambuc 
31433d6423SLionel Sambuc   return(r);
32433d6423SLionel Sambuc }
33433d6423SLionel Sambuc 
34433d6423SLionel Sambuc /*===========================================================================*
35433d6423SLionel Sambuc  *				send_work				     *
36433d6423SLionel Sambuc  *===========================================================================*/
send_work(void)37433d6423SLionel Sambuc void send_work(void)
38433d6423SLionel Sambuc {
39433d6423SLionel Sambuc /* Try to send out as many requests as possible */
40433d6423SLionel Sambuc   struct vmnt *vmp;
41433d6423SLionel Sambuc 
42433d6423SLionel Sambuc   if (sending == 0) return;
43433d6423SLionel Sambuc   for (vmp = &vmnt[0]; vmp < &vmnt[NR_MNTS]; vmp++)
44433d6423SLionel Sambuc 	fs_sendmore(vmp);
45433d6423SLionel Sambuc }
46433d6423SLionel Sambuc 
47433d6423SLionel Sambuc /*===========================================================================*
48433d6423SLionel Sambuc  *				fs_cancel				     *
49433d6423SLionel Sambuc  *===========================================================================*/
fs_cancel(struct vmnt * vmp)50433d6423SLionel Sambuc void fs_cancel(struct vmnt *vmp)
51433d6423SLionel Sambuc {
52433d6423SLionel Sambuc /* Cancel all pending requests for this vmp */
53433d6423SLionel Sambuc   struct worker_thread *worker;
54433d6423SLionel Sambuc 
55433d6423SLionel Sambuc   while ((worker = vmp->m_comm.c_req_queue) != NULL) {
56433d6423SLionel Sambuc 	vmp->m_comm.c_req_queue = worker->w_next;
57433d6423SLionel Sambuc 	worker->w_next = NULL;
58433d6423SLionel Sambuc 	sending--;
59433d6423SLionel Sambuc 	worker_stop(worker);
60433d6423SLionel Sambuc   }
61433d6423SLionel Sambuc }
62433d6423SLionel Sambuc 
63433d6423SLionel Sambuc /*===========================================================================*
64433d6423SLionel Sambuc  *				fs_sendmore				     *
65433d6423SLionel Sambuc  *===========================================================================*/
fs_sendmore(struct vmnt * vmp)66433d6423SLionel Sambuc void fs_sendmore(struct vmnt *vmp)
67433d6423SLionel Sambuc {
68433d6423SLionel Sambuc   struct worker_thread *worker;
69433d6423SLionel Sambuc 
70433d6423SLionel Sambuc   /* Can we send more requests? */
71433d6423SLionel Sambuc   if (vmp->m_fs_e == NONE) return;
72433d6423SLionel Sambuc   if ((worker = vmp->m_comm.c_req_queue) == NULL) /* No process is queued */
73433d6423SLionel Sambuc 	return;
74433d6423SLionel Sambuc   if (vmp->m_comm.c_cur_reqs >= vmp->m_comm.c_max_reqs)/*No room to send more*/
75433d6423SLionel Sambuc 	return;
76433d6423SLionel Sambuc   if (vmp->m_flags & VMNT_CALLBACK)	/* Hold off for now */
77433d6423SLionel Sambuc 	return;
78433d6423SLionel Sambuc 
79433d6423SLionel Sambuc   vmp->m_comm.c_req_queue = worker->w_next; /* Remove head */
80433d6423SLionel Sambuc   worker->w_next = NULL;
81433d6423SLionel Sambuc   sending--;
82433d6423SLionel Sambuc   assert(sending >= 0);
83433d6423SLionel Sambuc   (void) sendmsg(vmp, vmp->m_fs_e, worker);
84433d6423SLionel Sambuc }
85433d6423SLionel Sambuc 
86433d6423SLionel Sambuc /*===========================================================================*
87433d6423SLionel Sambuc  *				drv_sendrec				     *
88433d6423SLionel Sambuc  *===========================================================================*/
drv_sendrec(endpoint_t drv_e,message * reqmp)89433d6423SLionel Sambuc int drv_sendrec(endpoint_t drv_e, message *reqmp)
90433d6423SLionel Sambuc {
91433d6423SLionel Sambuc 	int r;
92433d6423SLionel Sambuc 	struct dmap *dp;
93433d6423SLionel Sambuc 
94433d6423SLionel Sambuc 	/* For the CTTY_MAJOR case, we would actually have to lock the device
95433d6423SLionel Sambuc 	 * entry being redirected to.  However, the CTTY major only hosts a
96433d6423SLionel Sambuc 	 * character device while this function is used only for block devices.
97433d6423SLionel Sambuc 	 * Thus, we can simply deny the request immediately.
98433d6423SLionel Sambuc 	 */
99433d6423SLionel Sambuc 	if (drv_e == CTTY_ENDPT) {
100433d6423SLionel Sambuc 		printf("VFS: /dev/tty is not a block device!\n");
101433d6423SLionel Sambuc 		return EIO;
102433d6423SLionel Sambuc 	}
103433d6423SLionel Sambuc 
104*e3b8d4bbSDavid van Moolenbroek 	if ((dp = get_dmap_by_endpt(drv_e)) == NULL)
105433d6423SLionel Sambuc 		panic("driver endpoint %d invalid", drv_e);
106433d6423SLionel Sambuc 
107433d6423SLionel Sambuc 	lock_dmap(dp);
108433d6423SLionel Sambuc 	if (dp->dmap_servicing != INVALID_THREAD)
109433d6423SLionel Sambuc 		panic("driver locking inconsistency");
110433d6423SLionel Sambuc 	dp->dmap_servicing = self->w_tid;
111433d6423SLionel Sambuc 	self->w_task = drv_e;
112433d6423SLionel Sambuc 	self->w_drv_sendrec = reqmp;
113433d6423SLionel Sambuc 
114433d6423SLionel Sambuc 	if ((r = asynsend3(drv_e, self->w_drv_sendrec, AMF_NOREPLY)) == OK) {
115433d6423SLionel Sambuc 		/* Yield execution until we've received the reply */
116433d6423SLionel Sambuc 		worker_wait();
11729e004d2SDavid van Moolenbroek 
118433d6423SLionel Sambuc 	} else {
119433d6423SLionel Sambuc 		printf("VFS: drv_sendrec: error sending msg to driver %d: %d\n",
120433d6423SLionel Sambuc 			drv_e, r);
12129e004d2SDavid van Moolenbroek 		self->w_drv_sendrec = NULL;
122433d6423SLionel Sambuc 	}
123433d6423SLionel Sambuc 
12429e004d2SDavid van Moolenbroek 	assert(self->w_drv_sendrec == NULL);
125433d6423SLionel Sambuc 	dp->dmap_servicing = INVALID_THREAD;
126433d6423SLionel Sambuc 	self->w_task = NONE;
127433d6423SLionel Sambuc 	unlock_dmap(dp);
12829e004d2SDavid van Moolenbroek 	return(r);
129433d6423SLionel Sambuc }
130433d6423SLionel Sambuc 
131433d6423SLionel Sambuc /*===========================================================================*
132433d6423SLionel Sambuc  *				fs_sendrec				     *
133433d6423SLionel Sambuc  *===========================================================================*/
fs_sendrec(endpoint_t fs_e,message * reqmp)134433d6423SLionel Sambuc int fs_sendrec(endpoint_t fs_e, message *reqmp)
135433d6423SLionel Sambuc {
136433d6423SLionel Sambuc   struct vmnt *vmp;
137433d6423SLionel Sambuc   int r;
138433d6423SLionel Sambuc 
139433d6423SLionel Sambuc   if ((vmp = find_vmnt(fs_e)) == NULL) {
140433d6423SLionel Sambuc 	printf("Trying to talk to non-existent FS endpoint %d\n", fs_e);
141433d6423SLionel Sambuc 	return(EIO);
142433d6423SLionel Sambuc   }
143433d6423SLionel Sambuc   if (fs_e == fp->fp_endpoint) return(EDEADLK);
144433d6423SLionel Sambuc 
14529e004d2SDavid van Moolenbroek   assert(self->w_sendrec == NULL);
146433d6423SLionel Sambuc   self->w_sendrec = reqmp;	/* Where to store request and reply */
147433d6423SLionel Sambuc 
148433d6423SLionel Sambuc   /* Find out whether we can send right away or have to enqueue */
149433d6423SLionel Sambuc   if (	!(vmp->m_flags & VMNT_CALLBACK) &&
150433d6423SLionel Sambuc 	vmp->m_comm.c_cur_reqs < vmp->m_comm.c_max_reqs) {
151433d6423SLionel Sambuc 	/* There's still room to send more and no proc is queued */
152433d6423SLionel Sambuc 	r = sendmsg(vmp, vmp->m_fs_e, self);
153433d6423SLionel Sambuc   } else {
154433d6423SLionel Sambuc 	r = queuemsg(vmp);
155433d6423SLionel Sambuc   }
156433d6423SLionel Sambuc   self->w_next = NULL;	/* End of list */
157433d6423SLionel Sambuc 
158433d6423SLionel Sambuc   if (r != OK) return(r);
159433d6423SLionel Sambuc 
160433d6423SLionel Sambuc   worker_wait();	/* Yield execution until we've received the reply. */
161433d6423SLionel Sambuc 
16229e004d2SDavid van Moolenbroek   assert(self->w_sendrec == NULL);
16329e004d2SDavid van Moolenbroek 
16410b7016bSDavid van Moolenbroek   r = reqmp->m_type;
16510b7016bSDavid van Moolenbroek   if (r == ERESTART)	/* ERESTART is used internally, so make sure it is.. */
16610b7016bSDavid van Moolenbroek 	r = EIO;	/* ..not delivered as a result from a file system. */
16710b7016bSDavid van Moolenbroek   return(r);
168433d6423SLionel Sambuc }
169433d6423SLionel Sambuc 
170433d6423SLionel Sambuc /*===========================================================================*
171433d6423SLionel Sambuc  *				vm_sendrec				     *
172433d6423SLionel Sambuc  *===========================================================================*/
vm_sendrec(message * reqmp)173433d6423SLionel Sambuc int vm_sendrec(message *reqmp)
174433d6423SLionel Sambuc {
175433d6423SLionel Sambuc   int r;
176433d6423SLionel Sambuc 
177433d6423SLionel Sambuc   assert(self);
178433d6423SLionel Sambuc   assert(reqmp);
179433d6423SLionel Sambuc 
18029e004d2SDavid van Moolenbroek   assert(self->w_sendrec == NULL);
181433d6423SLionel Sambuc   self->w_sendrec = reqmp;	/* Where to store request and reply */
182433d6423SLionel Sambuc 
183433d6423SLionel Sambuc   r = sendmsg(NULL, VM_PROC_NR, self);
184433d6423SLionel Sambuc 
185433d6423SLionel Sambuc   self->w_next = NULL;	/* End of list */
186433d6423SLionel Sambuc 
187433d6423SLionel Sambuc   if (r != OK) return(r);
188433d6423SLionel Sambuc 
189433d6423SLionel Sambuc   worker_wait();	/* Yield execution until we've received the reply. */
190433d6423SLionel Sambuc 
19129e004d2SDavid van Moolenbroek   assert(self->w_sendrec == NULL);
19229e004d2SDavid van Moolenbroek 
193433d6423SLionel Sambuc   return(reqmp->m_type);
194433d6423SLionel Sambuc }
195433d6423SLionel Sambuc 
196433d6423SLionel Sambuc 
197433d6423SLionel Sambuc /*===========================================================================*
198433d6423SLionel Sambuc  *                                vm_vfs_procctl_handlemem                   *
199433d6423SLionel Sambuc  *===========================================================================*/
vm_vfs_procctl_handlemem(endpoint_t ep,vir_bytes mem,vir_bytes len,int flags)200433d6423SLionel Sambuc int vm_vfs_procctl_handlemem(endpoint_t ep,
201433d6423SLionel Sambuc         vir_bytes mem, vir_bytes len, int flags)
202433d6423SLionel Sambuc {
203433d6423SLionel Sambuc     message m;
204433d6423SLionel Sambuc 
205433d6423SLionel Sambuc     /* main thread can not be suspended */
206433d6423SLionel Sambuc     if(!self) return EFAULT;
207433d6423SLionel Sambuc 
208433d6423SLionel Sambuc     memset(&m, 0, sizeof(m));
209433d6423SLionel Sambuc 
210433d6423SLionel Sambuc     m.m_type = VM_PROCCTL;
211433d6423SLionel Sambuc     m.VMPCTL_WHO = ep;
212433d6423SLionel Sambuc     m.VMPCTL_PARAM = VMPPARAM_HANDLEMEM;
213433d6423SLionel Sambuc     m.VMPCTL_M1 = mem;
214433d6423SLionel Sambuc     m.VMPCTL_LEN = len;
215433d6423SLionel Sambuc     m.VMPCTL_FLAGS = flags;
216433d6423SLionel Sambuc 
217433d6423SLionel Sambuc     return vm_sendrec(&m);
218433d6423SLionel Sambuc }
219433d6423SLionel Sambuc 
220433d6423SLionel Sambuc /*===========================================================================*
221433d6423SLionel Sambuc  *				queuemsg				     *
222433d6423SLionel Sambuc  *===========================================================================*/
queuemsg(struct vmnt * vmp)223433d6423SLionel Sambuc static int queuemsg(struct vmnt *vmp)
224433d6423SLionel Sambuc {
225433d6423SLionel Sambuc /* Put request on queue for vmnt */
226433d6423SLionel Sambuc 
227433d6423SLionel Sambuc   struct worker_thread *queue;
228433d6423SLionel Sambuc 
229433d6423SLionel Sambuc   if (vmp->m_comm.c_req_queue == NULL) {
230433d6423SLionel Sambuc 	vmp->m_comm.c_req_queue = self;
231433d6423SLionel Sambuc   } else {
232433d6423SLionel Sambuc 	/* Walk the list ... */
233433d6423SLionel Sambuc 	queue = vmp->m_comm.c_req_queue;
234433d6423SLionel Sambuc 	while (queue->w_next != NULL) queue = queue->w_next;
235433d6423SLionel Sambuc 
236433d6423SLionel Sambuc 	/* ... and append this worker */
237433d6423SLionel Sambuc 	queue->w_next = self;
238433d6423SLionel Sambuc   }
239433d6423SLionel Sambuc 
240433d6423SLionel Sambuc   self->w_next = NULL;	/* End of list */
241433d6423SLionel Sambuc   sending++;
242433d6423SLionel Sambuc 
243433d6423SLionel Sambuc   return(OK);
244433d6423SLionel Sambuc }
245