2 #include <minix/vfsif.h>
6 static int sendmsg(struct vmnt
*vmp
, endpoint_t dst
, struct worker_thread
*wp
);
7 static int queuemsg(struct vmnt
*vmp
);
9 /*===========================================================================*
11 *===========================================================================*/
12 static int sendmsg(struct vmnt
*vmp
, endpoint_t dst
, struct worker_thread
*wp
)
14 /* This is the low level function that sends requests.
15 * Currently to FSes or VM.
19 if(vmp
) vmp
->m_comm
.c_cur_reqs
++; /* One more request awaiting a reply */
20 transid
= wp
->w_tid
+ VFS_TRANSID
;
21 wp
->w_sendrec
->m_type
= TRNS_ADD_ID(wp
->w_sendrec
->m_type
, transid
);
23 if ((r
= asynsend3(dst
, wp
->w_sendrec
, AMF_NOREPLY
)) != OK
) {
24 printf("VFS: sendmsg: error sending message. "
25 "dest: %d req_nr: %d err: %d\n", dst
,
26 wp
->w_sendrec
->m_type
, r
);
34 /*===========================================================================*
36 *===========================================================================*/
39 /* Try to send out as many requests as possible */
42 if (sending
== 0) return;
43 for (vmp
= &vmnt
[0]; vmp
< &vmnt
[NR_MNTS
]; vmp
++)
47 /*===========================================================================*
49 *===========================================================================*/
50 void fs_cancel(struct vmnt
*vmp
)
52 /* Cancel all pending requests for this vmp */
53 struct worker_thread
*worker
;
55 while ((worker
= vmp
->m_comm
.c_req_queue
) != NULL
) {
56 vmp
->m_comm
.c_req_queue
= worker
->w_next
;
57 worker
->w_next
= NULL
;
63 /*===========================================================================*
65 *===========================================================================*/
66 void fs_sendmore(struct vmnt
*vmp
)
68 struct worker_thread
*worker
;
70 /* Can we send more requests? */
71 if (vmp
->m_fs_e
== NONE
) return;
72 if ((worker
= vmp
->m_comm
.c_req_queue
) == NULL
) /* No process is queued */
74 if (vmp
->m_comm
.c_cur_reqs
>= vmp
->m_comm
.c_max_reqs
)/*No room to send more*/
76 if (vmp
->m_flags
& VMNT_CALLBACK
) /* Hold off for now */
79 vmp
->m_comm
.c_req_queue
= worker
->w_next
; /* Remove head */
80 worker
->w_next
= NULL
;
83 (void) sendmsg(vmp
, vmp
->m_fs_e
, worker
);
86 /*===========================================================================*
88 *===========================================================================*/
89 int drv_sendrec(endpoint_t drv_e
, message
*reqmp
)
94 /* For the CTTY_MAJOR case, we would actually have to lock the device
95 * entry being redirected to. However, the CTTY major only hosts a
96 * character device while this function is used only for block devices.
97 * Thus, we can simply deny the request immediately.
99 if (drv_e
== CTTY_ENDPT
) {
100 printf("VFS: /dev/tty is not a block device!\n");
104 if ((dp
= get_dmap(drv_e
)) == NULL
)
105 panic("driver endpoint %d invalid", drv_e
);
108 if (dp
->dmap_servicing
!= INVALID_THREAD
)
109 panic("driver locking inconsistency");
110 dp
->dmap_servicing
= self
->w_tid
;
111 self
->w_task
= drv_e
;
112 self
->w_drv_sendrec
= reqmp
;
114 if ((r
= asynsend3(drv_e
, self
->w_drv_sendrec
, AMF_NOREPLY
)) == OK
) {
115 /* Yield execution until we've received the reply */
118 printf("VFS: drv_sendrec: error sending msg to driver %d: %d\n",
123 dp
->dmap_servicing
= INVALID_THREAD
;
125 self
->w_drv_sendrec
= NULL
;
130 /*===========================================================================*
132 *===========================================================================*/
133 int fs_sendrec(endpoint_t fs_e
, message
*reqmp
)
138 if ((vmp
= find_vmnt(fs_e
)) == NULL
) {
139 printf("Trying to talk to non-existent FS endpoint %d\n", fs_e
);
142 if (fs_e
== fp
->fp_endpoint
) return(EDEADLK
);
144 self
->w_sendrec
= reqmp
; /* Where to store request and reply */
146 /* Find out whether we can send right away or have to enqueue */
147 if ( !(vmp
->m_flags
& VMNT_CALLBACK
) &&
148 vmp
->m_comm
.c_cur_reqs
< vmp
->m_comm
.c_max_reqs
) {
149 /* There's still room to send more and no proc is queued */
150 r
= sendmsg(vmp
, vmp
->m_fs_e
, self
);
154 self
->w_next
= NULL
; /* End of list */
156 if (r
!= OK
) return(r
);
158 worker_wait(); /* Yield execution until we've received the reply. */
160 return(reqmp
->m_type
);
163 /*===========================================================================*
165 *===========================================================================*/
166 int vm_sendrec(message
*reqmp
)
173 self
->w_sendrec
= reqmp
; /* Where to store request and reply */
175 r
= sendmsg(NULL
, VM_PROC_NR
, self
);
177 self
->w_next
= NULL
; /* End of list */
179 if (r
!= OK
) return(r
);
181 worker_wait(); /* Yield execution until we've received the reply. */
183 return(reqmp
->m_type
);
187 /*===========================================================================*
188 * vm_vfs_procctl_handlemem *
189 *===========================================================================*/
190 int vm_vfs_procctl_handlemem(endpoint_t ep
,
191 vir_bytes mem
, vir_bytes len
, int flags
)
195 /* main thread can not be suspended */
196 if(!self
) return EFAULT
;
198 memset(&m
, 0, sizeof(m
));
200 m
.m_type
= VM_PROCCTL
;
202 m
.VMPCTL_PARAM
= VMPPARAM_HANDLEMEM
;
205 m
.VMPCTL_FLAGS
= flags
;
207 return vm_sendrec(&m
);
210 /*===========================================================================*
212 *===========================================================================*/
213 static int queuemsg(struct vmnt
*vmp
)
215 /* Put request on queue for vmnt */
217 struct worker_thread
*queue
;
219 if (vmp
->m_comm
.c_req_queue
== NULL
) {
220 vmp
->m_comm
.c_req_queue
= self
;
222 /* Walk the list ... */
223 queue
= vmp
->m_comm
.c_req_queue
;
224 while (queue
->w_next
!= NULL
) queue
= queue
->w_next
;
226 /* ... and append this worker */
227 queue
->w_next
= self
;
230 self
->w_next
= NULL
; /* End of list */