panic() cleanup.
[minix.git] / servers / iso9660fs / device.c
blob623eda53090ea2dd920c212b953c705f35faab1a
1 #include "inc.h"
2 #include <minix/vfsif.h>
4 PRIVATE int dummyproc;
6 FORWARD _PROTOTYPE( int safe_io_conversion, (endpoint_t, cp_grant_id_t *,
7 int *, cp_grant_id_t *, int,
8 endpoint_t *, void **, int *,
9 vir_bytes));
10 FORWARD _PROTOTYPE( void safe_io_cleanup, (cp_grant_id_t, cp_grant_id_t *,
11 int));
12 FORWARD _PROTOTYPE( int gen_opcl, (endpoint_t driver_e, int op,
13 Dev_t dev, int proc_e, int flags));
14 FORWARD _PROTOTYPE( int gen_io, (int task_nr, message *mess_ptr));
17 /*===========================================================================*
18 * fs_new_driver *
19 *===========================================================================*/
20 PUBLIC int fs_new_driver(void)
22 /* New driver endpoint for this device */
23 driver_endpoints[(fs_m_in.REQ_DEV >> MAJOR) & BYTE].driver_e =
24 fs_m_in.REQ_DRIVER_E;
25 return(OK);
29 /*===========================================================================*
30 * safe_io_conversion *
31 *===========================================================================*/
32 PRIVATE int safe_io_conversion(driver, gid, op, gids, gids_size,
33 io_ept, buf, vec_grants, bytes)
34 endpoint_t driver;
35 cp_grant_id_t *gid;
36 int *op;
37 cp_grant_id_t *gids;
38 int gids_size;
39 endpoint_t *io_ept;
40 void **buf;
41 int *vec_grants;
42 vir_bytes bytes;
44 int access = 0, size;
45 int j;
46 iovec_t *v;
47 static iovec_t new_iovec[NR_IOREQS];
49 /* Number of grants allocated in vector I/O. */
50 *vec_grants = 0;
52 /* Driver can handle it - change request to a safe one. */
54 *gid = GRANT_INVALID;
56 switch(*op) {
57 case MFS_DEV_READ:
58 case MFS_DEV_WRITE:
59 /* Change to safe op. */
60 *op = *op == MFS_DEV_READ ? DEV_READ_S : DEV_WRITE_S;
62 if((*gid=cpf_grant_direct(driver, (vir_bytes) *buf,
63 bytes, *op == DEV_READ_S ? CPF_WRITE :
64 CPF_READ)) < 0) {
65 panic("cpf_grant_magic of buffer failed");
68 break;
69 case MFS_DEV_GATHER:
70 case MFS_DEV_SCATTER:
71 /* Change to safe op. */
72 *op = *op == MFS_DEV_GATHER ?
73 DEV_GATHER_S : DEV_SCATTER_S;
75 /* Grant access to my new i/o vector. */
76 if((*gid = cpf_grant_direct(driver,
77 (vir_bytes) new_iovec, bytes * sizeof(iovec_t),
78 CPF_READ | CPF_WRITE)) < 0) {
79 panic("cpf_grant_direct of vector failed");
81 v = (iovec_t *) *buf;
82 /* Grant access to i/o buffers. */
83 for(j = 0; j < bytes; j++) {
84 if(j >= NR_IOREQS)
85 panic("vec too big: %d", bytes);
86 new_iovec[j].iov_addr = gids[j] =
87 cpf_grant_direct(driver, (vir_bytes)
88 v[j].iov_addr, v[j].iov_size,
89 *op == DEV_GATHER_S ? CPF_WRITE : CPF_READ);
90 if(!GRANT_VALID(gids[j])) {
91 panic("mfs: grant to iovec buf failed");
93 new_iovec[j].iov_size = v[j].iov_size;
94 (*vec_grants)++;
97 /* Set user's vector to the new one. */
98 *buf = new_iovec;
99 break;
102 /* If we have converted to a safe operation, I/O
103 * endpoint becomes FS if it wasn't already.
105 if(GRANT_VALID(*gid)) {
106 *io_ept = SELF_E;
107 return 1;
110 /* Not converted to a safe operation (because there is no
111 * copying involved in this operation).
113 return 0;
117 /*===========================================================================*
118 * safe_io_cleanup *
119 *===========================================================================*/
120 PRIVATE void safe_io_cleanup(gid, gids, gids_size)
121 cp_grant_id_t gid;
122 cp_grant_id_t *gids;
123 int gids_size;
125 /* Free resources (specifically, grants) allocated by safe_io_conversion(). */
126 int j;
128 cpf_revoke(gid);
130 for(j = 0; j < gids_size; j++)
131 cpf_revoke(gids[j]);
133 return;
137 /*===========================================================================*
138 * dev_open *
139 *===========================================================================*/
140 PUBLIC int dev_open(driver_e, dev, proc, flags)
141 endpoint_t driver_e;
142 dev_t dev; /* device to open */
143 int proc; /* process to open for */
144 int flags; /* mode bits and flags */
146 int major, r;
148 /* Determine the major device number call the device class specific
149 * open/close routine. (This is the only routine that must check the
150 * device number for being in range. All others can trust this check.)
152 major = (dev >> MAJOR) & BYTE;
153 if (major >= NR_DEVICES) major = 0;
154 r = gen_opcl(driver_e, DEV_OPEN, dev, proc, flags);
155 if (r == SUSPEND) panic("suspend on open from");
156 return(r);
160 /*===========================================================================*
161 * block_dev_io *
162 *===========================================================================*/
163 PUBLIC int block_dev_io(op, dev, proc_e, buf, pos, bytes, flags)
164 int op; /* MFS_DEV_READ, MFS_DEV_WRITE, etc. */
165 dev_t dev; /* major-minor device number */
166 int proc_e; /* in whose address space is buf? */
167 void *buf; /* virtual address of the buffer */
168 u64_t pos; /* byte position */
169 int bytes; /* how many bytes to transfer */
170 int flags; /* special flags, like O_NONBLOCK */
172 /* Read or write from a device. The parameter 'dev' tells which one. */
173 struct dmap *dp;
174 int r, safe;
175 message m;
176 iovec_t *v;
177 cp_grant_id_t gid = GRANT_INVALID;
178 int vec_grants;
179 int op_used;
180 void *buf_used;
181 static cp_grant_id_t gids[NR_IOREQS];
182 endpoint_t driver_e;
184 /* Determine driver endpoint for this device */
185 driver_e = driver_endpoints[(dev >> MAJOR) & BYTE].driver_e;
187 /* See if driver is roughly valid. */
188 if (driver_e == NONE) return(EDEADSRCDST);
190 /* The io vector copying relies on this I/O being for FS itself. */
191 if(proc_e != SELF_E) {
192 printf("ISOFS(%d) doing block_dev_io for non-self %d\n", SELF_E, proc_e);
193 panic("doing block_dev_io for non-self: %d", proc_e);
196 /* By default, these are right. */
197 m.IO_ENDPT = proc_e;
198 m.ADDRESS = buf;
199 buf_used = buf;
201 /* Convert parameters to 'safe mode'. */
202 op_used = op;
203 safe = safe_io_conversion(driver_e, &gid,
204 &op_used, gids, NR_IOREQS, &m.IO_ENDPT, &buf_used,
205 &vec_grants, bytes);
207 /* Set up rest of the message. */
208 if (safe) m.IO_GRANT = (char *) gid;
210 m.m_type = op_used;
211 m.DEVICE = (dev >> MINOR) & BYTE;
212 m.POSITION = ex64lo(pos);
213 m.COUNT = bytes;
214 m.HIGHPOS = ex64hi(pos);
216 /* Call the task. */
217 r = sendrec(driver_e, &m);
219 /* As block I/O never SUSPENDs, safe cleanup must be done whether
220 * the I/O succeeded or not. */
221 if (safe) safe_io_cleanup(gid, gids, vec_grants);
223 /* RECOVERY:
224 * - send back dead driver number
225 * - VFS unmaps it, waits for new driver
226 * - VFS sends the new driver endp for the FS proc and the request again
228 if (r != OK) {
229 if (r == EDEADSRCDST) {
230 printf("ISOFS(%d) dead driver %d\n", SELF_E, driver_e);
231 driver_endpoints[(dev >> MAJOR) & BYTE].driver_e = NONE;
232 return(r);
234 else if (r == ELOCKED) {
235 return(r);
237 else
238 panic("call_task: can't send/receive: %d", r);
239 } else {
240 /* Did the process we did the sendrec() for get a result? */
241 if (m.REP_ENDPT != proc_e) {
242 printf("ISOFS (%d) strange device reply from %d, type = %d, proc = %d (not %d) (2) ignored\n", SELF_E, m.m_source, m.m_type, proc_e, m.REP_ENDPT);
243 r = EIO;
247 /* Task has completed. See if call completed. */
248 if (m.REP_STATUS == SUSPEND) {
249 panic("ISOFS block_dev_io: driver returned SUSPEND");
252 if(buf != buf_used && r == OK) {
253 memcpy(buf, buf_used, bytes * sizeof(iovec_t));
256 return(m.REP_STATUS);
260 /*===========================================================================*
261 * gen_opcl *
262 *===========================================================================*/
263 PRIVATE int gen_opcl(driver_e, op, dev, proc_e, flags)
264 endpoint_t driver_e;
265 int op; /* operation, DEV_OPEN or DEV_CLOSE */
266 dev_t dev; /* device to open or close */
267 int proc_e; /* process to open/close for */
268 int flags; /* mode bits and flags */
270 /* Called from the dmap struct in table.c on opens & closes of special files.*/
271 message dev_mess;
273 dev_mess.m_type = op;
274 dev_mess.DEVICE = (dev >> MINOR) & BYTE;
275 dev_mess.IO_ENDPT = proc_e;
276 dev_mess.COUNT = flags;
278 /* Call the task. */
279 gen_io(driver_e, &dev_mess);
281 return(dev_mess.REP_STATUS);
285 /*===========================================================================*
286 * gen_io *
287 *===========================================================================*/
288 PRIVATE int gen_io(task_nr, mess_ptr)
289 int task_nr; /* which task to call */
290 message *mess_ptr; /* pointer to message for task */
292 /* All file system I/O ultimately comes down to I/O on major/minor device
293 * pairs. These lead to calls on the following routines via the dmap table.
296 int r, proc_e;
298 proc_e = mess_ptr->IO_ENDPT;
300 r = sendrec(task_nr, mess_ptr);
301 if (r != OK) {
302 if (r == EDEADSRCDST) {
303 printf("fs: dead driver %d\n", task_nr);
304 panic("should handle crashed drivers");
305 /* dmap_unmap_by_endpt(task_nr); */
306 return r;
308 if (r == ELOCKED) {
309 printf("fs: ELOCKED talking to %d\n", task_nr);
310 return r;
312 panic("call_task: can't send/receive: %d", r);
315 /* Did the process we did the sendrec() for get a result? */
316 if (mess_ptr->REP_ENDPT != proc_e) {
317 printf(
318 "fs: strange device reply from %d, type = %d, proc = %d (not %d) (2) ignored\n",
319 mess_ptr->m_source,
320 mess_ptr->m_type,
321 proc_e,
322 mess_ptr->REP_ENDPT);
323 return(EIO);
326 return(OK);
330 /*===========================================================================*
331 * dev_close *
332 *===========================================================================*/
333 PUBLIC void dev_close(driver_e, dev)
334 endpoint_t driver_e;
335 dev_t dev; /* device to close */
337 (void) gen_opcl(driver_e, DEV_CLOSE, dev, 0, 0);