use oxpcie only if enabled to avoid baud bottleneck of uart.
[minix.git] / drivers / filter / driver.c
blob77582b3c36d21036c3513e0774ba5b628e6691c3
1 /* Filter driver - lowest layer - disk driver management */
3 #include "inc.h"
5 /* Drivers. */
6 static struct driverinfo driver[2];
8 /* State variables. */
9 static endpoint_t self_ep;
10 static asynmsg_t amsgtable[2];
12 static int size_known = 0;
13 static u64_t disk_size;
15 static int problem_stats[BD_LAST] = { 0 };
17 /*===========================================================================*
18 * driver_open *
19 *===========================================================================*/
20 static int driver_open(int which)
22 /* Perform an open or close operation on the driver. This is
23 * unfinished code: we should never be doing a blocking sendrec() to
24 * the driver.
26 message msg;
27 cp_grant_id_t gid;
28 struct partition part;
29 sector_t sectors;
30 int r;
32 msg.m_type = DEV_OPEN;
33 msg.DEVICE = driver[which].minor;
34 msg.IO_ENDPT = self_ep;
35 r = sendrec(driver[which].endpt, &msg);
37 if (r != OK) {
38 /* Should we restart the driver now? */
39 printf("Filter: driver_open: sendrec returned %d\n", r);
41 return RET_REDO;
44 if(msg.m_type != TASK_REPLY || msg.REP_STATUS != OK) {
45 printf("Filter: driver_open: sendrec returned %d, %d\n",
46 msg.m_type, msg.REP_STATUS);
48 return RET_REDO;
51 /* Take the opportunity to retrieve the hard disk size. */
52 gid = cpf_grant_direct(driver[which].endpt,
53 (vir_bytes) &part, sizeof(part), CPF_WRITE);
54 if(!GRANT_VALID(gid))
55 panic("invalid grant: %d", gid);
57 msg.m_type = DEV_IOCTL_S;
58 msg.REQUEST = DIOCGETP;
59 msg.DEVICE = driver[which].minor;
60 msg.IO_ENDPT = self_ep;
61 msg.IO_GRANT = (char *) gid;
63 r = sendrec(driver[which].endpt, &msg);
65 cpf_revoke(gid);
67 if (r != OK || msg.m_type != TASK_REPLY || msg.REP_STATUS != OK) {
68 /* Not sure what to do here, either. */
69 printf("Filter: ioctl(DIOCGETP) returned (%d, %d)\n",
70 r, msg.m_type);
72 return RET_REDO;
75 if(!size_known) {
76 disk_size = part.size;
77 size_known = 1;
78 sectors = div64u(disk_size, SECTOR_SIZE);
79 if(cmp64(mul64u(sectors, SECTOR_SIZE), disk_size)) {
80 printf("Filter: partition too large\n");
82 return RET_REDO;
84 #if DEBUG
85 printf("Filter: partition size: 0x%s / %lu sectors\n",
86 print64(disk_size), sectors);
87 #endif
88 } else {
89 if(cmp64(disk_size, part.size)) {
90 printf("Filter: partition size mismatch (%s != %s)\n",
91 print64(part.size), print64(disk_size));
93 return RET_REDO;
97 return OK;
100 /*===========================================================================*
101 * driver_close *
102 *===========================================================================*/
103 static int driver_close(int which)
105 message msg;
106 int r;
108 msg.m_type = DEV_CLOSE;
109 msg.DEVICE = driver[which].minor;
110 msg.IO_ENDPT = self_ep;
111 r = sendrec(driver[which].endpt, &msg);
113 if (r != OK) {
114 /* Should we restart the driver now? */
115 printf("Filter: driver_close: sendrec returned %d\n", r);
117 return RET_REDO;
120 if(msg.m_type != TASK_REPLY || msg.REP_STATUS != OK) {
121 printf("Filter: driver_close: sendrec returned %d, %d\n",
122 msg.m_type, msg.REP_STATUS);
124 return RET_REDO;
127 return OK;
130 /*===========================================================================*
131 * driver_init *
132 *===========================================================================*/
133 void driver_init(void)
135 /* Initialize the driver layer. */
136 int r;
138 self_ep = getprocnr();
140 memset(driver, 0, sizeof(driver));
142 /* Endpoints unknown. */
143 driver[DRIVER_MAIN].endpt = NONE;
144 driver[DRIVER_BACKUP].endpt = NONE;
146 /* Get disk driver's and this proc's endpoint. */
147 driver[DRIVER_MAIN].label = MAIN_LABEL;
148 driver[DRIVER_MAIN].minor = MAIN_MINOR;
150 /* No up received yet but expected when the driver starts. */
151 driver[DRIVER_MAIN].up_event = UP_EXPECTED;
152 driver[DRIVER_BACKUP].up_event = UP_EXPECTED;
154 r = ds_retrieve_label_endpt(driver[DRIVER_MAIN].label,
155 &driver[DRIVER_MAIN].endpt);
156 if (r != OK) {
157 printf("Filter: failed to get main disk driver's endpoint: "
158 "%d\n", r);
159 bad_driver(DRIVER_MAIN, BD_DEAD, EFAULT);
160 check_driver(DRIVER_MAIN);
162 else if (driver_open(DRIVER_MAIN) != OK) {
163 panic("unhandled driver_open failure");
166 if(USE_MIRROR) {
167 driver[DRIVER_BACKUP].label = BACKUP_LABEL;
168 driver[DRIVER_BACKUP].minor = BACKUP_MINOR;
170 if(!strcmp(driver[DRIVER_MAIN].label,
171 driver[DRIVER_BACKUP].label)) {
172 panic("same driver: not tested");
175 r = ds_retrieve_label_endpt(driver[DRIVER_BACKUP].label,
176 &driver[DRIVER_BACKUP].endpt);
177 if (r != OK) {
178 printf("Filter: failed to get backup disk driver's "
179 "endpoint: %d\n", r);
180 bad_driver(DRIVER_BACKUP, BD_DEAD, EFAULT);
181 check_driver(DRIVER_BACKUP);
183 else if (driver_open(DRIVER_BACKUP) != OK) {
184 panic("unhandled driver_open failure");
189 /*===========================================================================*
190 * driver_shutdown *
191 *===========================================================================*/
192 void driver_shutdown(void)
194 /* Clean up. */
196 #if DEBUG
197 printf("Filter: %u driver deaths, %u protocol errors, "
198 "%u data errors\n", problem_stats[BD_DEAD],
199 problem_stats[BD_PROTO], problem_stats[BD_DATA]);
200 #endif
202 if(driver_close(DRIVER_MAIN) != OK)
203 printf("Filter: DEV_CLOSE failed on shutdown (1)\n");
205 if(USE_MIRROR)
206 if(driver_close(DRIVER_BACKUP) != OK)
207 printf("Filter: DEV_CLOSE failed on shutdown (2)\n");
210 /*===========================================================================*
211 * get_raw_size *
212 *===========================================================================*/
213 u64_t get_raw_size(void)
215 /* Return the size of the raw disks as used by the filter driver.
218 return disk_size;
221 /*===========================================================================*
222 * reset_kills *
223 *===========================================================================*/
224 void reset_kills(void)
226 /* Reset kill and retry statistics. */
227 driver[DRIVER_MAIN].kills = 0;
228 driver[DRIVER_MAIN].retries = 0;
229 driver[DRIVER_BACKUP].kills = 0;
230 driver[DRIVER_BACKUP].retries = 0;
233 /*===========================================================================*
234 * bad_driver *
235 *===========================================================================*/
236 int bad_driver(int which, int type, int error)
238 /* A disk driver has died or produced an error. Mark it so that we can
239 * deal with it later, and return RET_REDO to indicate that the
240 * current operation is to be retried. Also store an error code to
241 * return to the user if the situation is unrecoverable.
243 driver[which].problem = type;
244 driver[which].error = error;
246 return RET_REDO;
249 /*===========================================================================*
250 * new_driver_ep *
251 *===========================================================================*/
252 static int new_driver_ep(int which)
254 /* See if a new driver instance has already been started for the given
255 * driver, by retrieving its entry from DS.
257 int r;
258 endpoint_t endpt;
260 r = ds_retrieve_label_endpt(driver[which].label, &endpt);
262 if (r != OK) {
263 printf("Filter: DS query for %s failed\n",
264 driver[which].label);
266 return 0;
269 if (endpt == driver[which].endpt) {
270 #if DEBUG
271 printf("Filter: same endpoint for %s\n", driver[which].label);
272 #endif
273 return 0;
276 #if DEBUG
277 printf("Filter: new enpdoint for %s: %d -> %d\n", driver[which].label,
278 driver[which].endpt, endpt);
279 #endif
281 driver[which].endpt = endpt;
283 return 1;
286 /*===========================================================================*
287 * check_problem *
288 *===========================================================================*/
289 static int check_problem(int which, int problem, int retries, int *tell_rs)
291 /* A problem has occurred with a driver. Update statistics, and decide
292 * what to do. If EAGAIN is returned, the driver should be restarted;
293 * any other result will be passed up.
296 #if DEBUG
297 printf("Filter: check_problem processing driver %d, problem %d\n",
298 which, problem);
299 #endif
301 problem_stats[problem]++;
303 if(new_driver_ep(which)) {
304 #if DEBUG
305 printf("Filter: check_problem: noticed a new driver\n");
306 #endif
308 if(driver_open(which) == OK) {
309 #if DEBUG2
310 printf("Filter: open OK -> no recovery\n");
311 #endif
312 return OK;
313 } else {
314 #if DEBUG2
315 printf("Filter: open not OK -> recovery\n");
316 #endif
317 problem = BD_PROTO;
318 problem_stats[problem]++;
322 /* If the driver has died, we always need to restart it. If it has
323 * been giving problems, we first retry the request, up to N times,
324 * after which we kill and restart the driver. We restart the driver
325 * up to M times, after which we remove the driver from the mirror
326 * configuration. If we are not set up to do mirroring, we can only
327 * do one thing, and that is continue to limp along with the bad
328 * driver..
330 switch(problem) {
331 case BD_PROTO:
332 case BD_DATA:
333 driver[which].retries++;
335 #if DEBUG
336 printf("Filter: disk driver %d has had "
337 "%d/%d retry attempts, %d/%d kills\n", which,
338 driver[which].retries, NR_RETRIES,
339 driver[which].kills, NR_RESTARTS);
340 #endif
342 if (driver[which].retries < NR_RETRIES) {
343 if(retries == 1) {
344 #if DEBUG
345 printf("Filter: not restarting; retrying "
346 "(retries %d/%d, kills %d/%d)\n",
347 driver[which].retries, NR_RETRIES,
348 driver[which].kills, NR_RESTARTS);
349 #endif
350 return OK;
352 #if DEBUG
353 printf("Filter: restarting (retries %d/%d, "
354 "kills %d/%d, internal retry %d)\n",
355 driver[which].retries, NR_RETRIES,
356 driver[which].kills, NR_RESTARTS, retries);
357 #endif
360 #if DEBUG
361 printf("Filter: disk driver %d has reached error "
362 "threshold, restarting driver\n", which);
363 #endif
365 *tell_rs = (driver[which].up_event != UP_PENDING);
366 break;
368 case BD_DEAD:
369 /* Can't kill that which is already dead.. */
370 *tell_rs = 0;
371 break;
373 default:
374 panic("invalid problem: %d", problem);
377 /* At this point, the driver will be restarted. */
378 driver[which].retries = 0;
379 driver[which].kills++;
381 if (driver[which].kills < NR_RESTARTS)
382 return EAGAIN;
384 /* We've reached the maximum number of restarts for this driver. */
385 if (USE_MIRROR) {
386 printf("Filter: kill threshold reached, disabling mirroring\n");
388 USE_MIRROR = 0;
390 if (which == DRIVER_MAIN) {
391 driver[DRIVER_MAIN] = driver[DRIVER_BACKUP];
393 /* This is not necessary. */
394 strcpy(MAIN_LABEL, BACKUP_LABEL);
395 MAIN_MINOR = BACKUP_MINOR;
398 driver[DRIVER_BACKUP].endpt = NONE;
400 return OK;
402 else {
403 /* We tried, we really did. But now we give up. Tell the user.
405 printf("Filter: kill threshold reached, returning error\n");
407 if (driver[which].error == EAGAIN) return EIO;
409 return driver[which].error;
413 /*===========================================================================*
414 * restart_driver *
415 *===========================================================================*/
416 static void restart_driver(int which, int tell_rs)
418 /* Restart the given driver. Block until the new instance is up.
420 message msg;
421 int ipc_status;
422 int r;
424 if (tell_rs) {
425 /* Tell RS to refresh or restart the driver */
426 msg.m_type = RS_REFRESH;
427 msg.RS_CMD_ADDR = driver[which].label;
428 msg.RS_CMD_LEN = strlen(driver[which].label);
430 #if DEBUG
431 printf("Filter: asking RS to refresh %s..\n",
432 driver[which].label);
433 #endif
435 r = sendrec(RS_PROC_NR, &msg);
437 if (r != OK || msg.m_type != OK)
438 panic("RS request failed: %d", r);
440 #if DEBUG
441 printf("Filter: RS call succeeded\n");
442 #endif
445 /* Wait until the new driver instance is up, and get its endpoint. */
446 #if DEBUG
447 printf("Filter: endpoint update driver %d; old endpoint %d\n",
448 which, driver[which].endpt);
449 #endif
451 if(driver[which].up_event == UP_EXPECTED) {
452 driver[which].up_event = UP_NONE;
454 while(driver[which].up_event != UP_PENDING) {
455 r = driver_receive(DS_PROC_NR, &msg, &ipc_status);
456 if(r != OK)
457 panic("driver_receive returned error: %d", r);
459 ds_event();
463 /*===========================================================================*
464 * check_driver *
465 *===========================================================================*/
466 int check_driver(int which)
468 /* See if the given driver has been troublesome, and if so, deal with
469 * it.
471 int problem, tell_rs;
472 int r, retries = 0;
474 problem = driver[which].problem;
476 if (problem == BD_NONE)
477 return OK;
479 do {
480 if(retries) {
481 #if DEBUG
482 printf("Filter: check_driver: retry number %d\n",
483 retries);
484 #endif
485 problem = BD_PROTO;
487 retries++;
488 driver[which].problem = BD_NONE;
490 /* Decide what to do: continue operation, restart the driver,
491 * or return an error.
493 r = check_problem(which, problem, retries, &tell_rs);
494 if (r != EAGAIN)
495 return r;
497 /* Restarting the driver it is. First tell RS (if necessary),
498 * then wait for the new driver instance to come up.
500 restart_driver(which, tell_rs);
502 /* Finally, open the device on the new driver */
503 } while (driver_open(which) != OK);
505 #if DEBUG
506 printf("Filter: check_driver restarted driver %d, endpoint %d\n",
507 which, driver[which].endpt);
508 #endif
510 return OK;
513 /*===========================================================================*
514 * flt_senda *
515 *===========================================================================*/
516 static int flt_senda(message *mess, int which)
518 /* Send a message to one driver. Can only return OK at the moment. */
519 int r;
520 asynmsg_t *amp;
522 /* Fill in the last bits of the message. */
523 mess->DEVICE = driver[which].minor;
524 mess->IO_ENDPT = self_ep;
526 /* Send the message asynchronously. */
527 amp = &amsgtable[which];
528 amp->dst = driver[which].endpt;
529 amp->msg = *mess;
530 amp->flags = AMF_VALID;
531 r = senda(amsgtable, 2);
533 if(r != OK)
534 panic("senda returned error: %d", r);
536 return r;
539 /*===========================================================================*
540 * check_senda *
541 *===========================================================================*/
542 static int check_senda(int which)
544 /* Check whether an earlier senda resulted in an error indicating the
545 * message never got delivered. Only in that case can we reliably say
546 * that the driver died. Return BD_DEAD in this case, and BD_PROTO
547 * otherwise.
549 asynmsg_t *amp;
551 amp = &amsgtable[which];
553 if ((amp->flags & AMF_DONE) && (amp->result == EDEADSRCDST)) {
555 return BD_DEAD;
558 return BD_PROTO;
561 /*===========================================================================*
562 * flt_receive *
563 *===========================================================================*/
564 static int flt_receive(message *mess, int which)
566 /* Receive a message from one or either driver, unless a timeout
567 * occurs. Can only return OK or RET_REDO.
569 int r;
570 int ipc_status;
572 for (;;) {
573 r = driver_receive(ANY, mess, &ipc_status);
574 if(r != OK)
575 panic("driver_receive returned error: %d", r);
577 if(mess->m_source == DS_PROC_NR && is_ipc_notify(ipc_status)) {
578 ds_event();
579 continue;
582 if(mess->m_source == CLOCK && is_ipc_notify(ipc_status)) {
583 if (mess->NOTIFY_TIMESTAMP < flt_alarm(-1)) {
584 #if DEBUG
585 printf("Filter: SKIPPING old alarm "
586 "notification\n");
587 #endif
588 continue;
591 #if DEBUG
592 printf("Filter: timeout waiting for disk driver %d "
593 "reply!\n", which);
594 #endif
596 /* If we're waiting for either driver,
597 * both are at fault.
599 if (which < 0) {
600 bad_driver(DRIVER_MAIN,
601 check_senda(DRIVER_MAIN), EFAULT);
603 return bad_driver(DRIVER_BACKUP,
604 check_senda(DRIVER_BACKUP), EFAULT);
607 /* Otherwise, just report the one not replying as dead.
609 return bad_driver(which, check_senda(which), EFAULT);
612 if (mess->m_source != driver[DRIVER_MAIN].endpt &&
613 mess->m_source != driver[DRIVER_BACKUP].endpt) {
614 #if DEBUG
615 printf("Filter: got STRAY message %d from %d\n",
616 mess->m_type, mess->m_source);
617 #endif
619 continue;
622 /* We are waiting for a reply from one specific driver. */
623 if (which >= 0) {
624 /* If the message source is that driver, good. */
625 if (mess->m_source == driver[which].endpt)
626 break;
628 /* This should probably be treated as a real protocol
629 * error. We do not abort any receives (not even paired
630 * receives) except because of timeouts. Getting here
631 * means a driver replied at least the timeout period
632 * later than expected, which should be enough reason
633 * to kill it really. The other explanation is that it
634 * is actually violating the protocol and sending bogus
635 * messages...
637 #if DEBUG
638 printf("Filter: got UNEXPECTED reply from %d\n",
639 mess->m_source);
640 #endif
642 continue;
645 /* We got a message from one of the drivers, and we didn't
646 * care which one we wanted to receive from. A-OK.
648 break;
651 return OK;
654 /*===========================================================================*
655 * flt_sendrec *
656 *===========================================================================*/
657 static int flt_sendrec(message *mess, int which)
659 int r;
661 r = flt_senda(mess, which);
662 if(r != OK)
663 return r;
665 if(check_senda(which) == BD_DEAD) {
666 return bad_driver(which, BD_DEAD, EFAULT);
669 /* Set alarm. */
670 flt_alarm(DRIVER_TIMEOUT);
672 r = flt_receive(mess, which);
674 /* Clear the alarm. */
675 flt_alarm(0);
676 return r;
679 /*===========================================================================*
680 * do_sendrec_both *
681 *===========================================================================*/
682 static int do_sendrec_both(message *m1, message *m2)
684 /* If USEE_MIRROR is set, call flt_sendrec() to both drivers.
685 * Otherwise, only call flt_sendrec() to the main driver.
686 * This function will only return either OK or RET_REDO.
688 int r, which = -1;
689 message ma, mb;
691 /* If the two disks use the same driver, call flt_sendrec() twice
692 * sequentially. Such a setup is not very useful though.
694 if (!strcmp(driver[DRIVER_MAIN].label, driver[DRIVER_BACKUP].label)) {
695 if ((r = flt_sendrec(m1, DRIVER_MAIN)) != OK) return r;
696 return flt_sendrec(m2, DRIVER_BACKUP);
699 /* If the two disks use different drivers, call flt_senda()
700 * twice, and then flt_receive(), and distinguish the return
701 * messages by means of m_source.
703 if ((r = flt_senda(m1, DRIVER_MAIN)) != OK) return r;
704 if ((r = flt_senda(m2, DRIVER_BACKUP)) != OK) return r;
706 /* Set alarm. */
707 flt_alarm(DRIVER_TIMEOUT);
709 /* The message received by the 1st flt_receive() may not be
710 * from DRIVER_MAIN.
712 if ((r = flt_receive(&ma, -1)) != OK) {
713 flt_alarm(0);
714 return r;
717 if (ma.m_source == driver[DRIVER_MAIN].endpt) {
718 which = DRIVER_BACKUP;
719 } else if (ma.m_source == driver[DRIVER_BACKUP].endpt) {
720 which = DRIVER_MAIN;
721 } else {
722 panic("message from unexpected source: %d",
723 ma.m_source);
726 r = flt_receive(&mb, which);
728 /* Clear the alarm. */
729 flt_alarm(0);
731 if(r != OK)
732 return r;
734 if (ma.m_source == driver[DRIVER_MAIN].endpt) {
735 *m1 = ma;
736 *m2 = mb;
737 } else {
738 *m1 = mb;
739 *m2 = ma;
742 return OK;
745 /*===========================================================================*
746 * do_sendrec_one *
747 *===========================================================================*/
748 static int do_sendrec_one(message *m1, const message *m2)
750 /* Only talk to the main driver. If something goes wrong, it will
751 * be fixed elsewhere.
752 * This function will only return either OK or RET_REDO.
755 return flt_sendrec(m1, DRIVER_MAIN);
758 /*===========================================================================*
759 * paired_sendrec *
760 *===========================================================================*/
761 static int paired_sendrec(message *m1, message *m2, int both)
763 /* Sendrec with the disk driver. If the disk driver is down, and was
764 * restarted, redo the request, until the driver works fine, or can't
765 * be restarted again.
767 int r;
769 #if DEBUG2
770 printf("paired_sendrec(%d) - <%d,%x:%x,%d> - %x,%x\n",
771 both, m1->m_type, m1->HIGHPOS, m1->POSITION, m1->COUNT,
772 m1->IO_GRANT, m2->IO_GRANT);
773 #endif
775 if (both)
776 r = do_sendrec_both(m1, m2);
777 else
778 r = do_sendrec_one(m1, m2);
780 #if DEBUG2
781 if (r != OK)
782 printf("paired_sendrec about to return %d\n", r);
783 #endif
785 return r;
788 /*===========================================================================*
789 * single_grant *
790 *===========================================================================*/
791 static int single_grant(endpoint_t endpt, vir_bytes buf, int access,
792 cp_grant_id_t *gid, iovec_s_t vector[NR_IOREQS], const size_t *sizep)
794 /* Create grants for a vectored request to a single driver.
796 cp_grant_id_t grant;
797 size_t size, chunk;
798 int count;
800 size = *sizep;
802 /* Split up the request into chunks, if requested. This makes no
803 * difference at all, except that this works around a weird performance
804 * bug with large DMA PRDs on some machines.
806 if (CHUNK_SIZE > 0) chunk = CHUNK_SIZE;
807 else chunk = size;
809 /* Fill in the vector, creating a grant for each item. */
810 for (count = 0; size > 0 && count < NR_IOREQS; count++) {
811 /* The last chunk will contain all the remaining data. */
812 if (chunk > size || count == NR_IOREQS - 1)
813 chunk = size;
815 grant = cpf_grant_direct(endpt, buf, chunk, access);
816 if (!GRANT_VALID(grant))
817 panic("invalid grant: %d", grant);
819 vector[count].iov_grant = grant;
820 vector[count].iov_size = chunk;
822 buf += chunk;
823 size -= chunk;
826 /* Then create a grant for the vector itself. */
827 *gid = cpf_grant_direct(endpt, (vir_bytes) vector,
828 sizeof(vector[0]) * count, CPF_READ | CPF_WRITE);
830 if (!GRANT_VALID(*gid))
831 panic("invalid grant: %d", *gid);
833 return count;
836 /*===========================================================================*
837 * paired_grant *
838 *===========================================================================*/
839 static int paired_grant(char *buf1, char *buf2, int request,
840 cp_grant_id_t *gids, iovec_s_t vectors[2][NR_IOREQS], size_t *sizes,
841 int both)
843 /* Create memory grants, either to one or to both drivers.
845 int count, access;
847 count = 0;
848 access = (request == FLT_WRITE) ? CPF_READ : CPF_WRITE;
850 if(driver[DRIVER_MAIN].endpt > 0) {
851 count = single_grant(driver[DRIVER_MAIN].endpt,
852 (vir_bytes) buf1, access, &gids[0], vectors[0],
853 &sizes[0]);
856 if (both) {
857 if(driver[DRIVER_BACKUP].endpt > 0) {
858 count = single_grant(driver[DRIVER_BACKUP].endpt,
859 (vir_bytes) buf2, access, &gids[1],
860 vectors[1], &sizes[1]);
863 return count;
866 /*===========================================================================*
867 * single_revoke *
868 *===========================================================================*/
869 PRIVATE void single_revoke(cp_grant_id_t gid, const iovec_s_t vector[NR_IOREQS],
870 size_t *sizep, int count)
872 /* Revoke all grants associated with a request to a single driver.
873 * Modify the given size to reflect the actual I/O performed.
875 int i;
877 /* Revoke the grants for all the elements of the vector. */
878 for (i = 0; i < count; i++) {
879 cpf_revoke(vector[i].iov_grant);
880 *sizep -= vector[i].iov_size;
883 /* Then revoke the grant for the vector itself. */
884 cpf_revoke(gid);
887 /*===========================================================================*
888 * paired_revoke *
889 *===========================================================================*/
890 static void paired_revoke(const cp_grant_id_t *gids,
891 iovec_s_t vectors[2][NR_IOREQS],
892 size_t *sizes, int count, int both)
894 /* Revoke grants to drivers for a single request.
897 single_revoke(gids[0], vectors[0], &sizes[0], count);
899 if (both)
900 single_revoke(gids[1], vectors[1], &sizes[1], count);
903 /*===========================================================================*
904 * read_write *
905 *===========================================================================*/
906 int read_write(u64_t pos, char *bufa, char *bufb, size_t *sizep, int request)
908 iovec_s_t vectors[2][NR_IOREQS];
909 message m1, m2;
910 cp_grant_id_t gids[2];
911 size_t sizes[2];
912 int r, both, count;
914 gids[0] = gids[1] = GRANT_INVALID;
915 sizes[0] = sizes[1] = *sizep;
917 /* Send two requests only if mirroring is enabled and the given request
918 * is either FLT_READ2 or FLT_WRITE.
920 both = (USE_MIRROR && request != FLT_READ);
922 count = paired_grant(bufa, bufb, request, gids, vectors, sizes, both);
924 m1.m_type = (request == FLT_WRITE) ? DEV_SCATTER_S : DEV_GATHER_S;
925 m1.COUNT = count;
926 m1.POSITION = ex64lo(pos);
927 m1.HIGHPOS = ex64hi(pos);
929 m2 = m1;
931 m1.IO_GRANT = (char *) gids[0];
932 m2.IO_GRANT = (char *) gids[1];
934 r = paired_sendrec(&m1, &m2, both);
936 paired_revoke(gids, vectors, sizes, count, both);
938 if(r != OK) {
939 #if DEBUG
940 if (r != RET_REDO)
941 printf("Filter: paired_sendrec returned %d\n", r);
942 #endif
943 return r;
946 if (m1.m_type != TASK_REPLY || m1.REP_STATUS != OK) {
947 printf("Filter: unexpected/invalid reply from main driver: "
948 "(%x, %d)\n", m1.m_type, m1.REP_STATUS);
950 return bad_driver(DRIVER_MAIN, BD_PROTO,
951 (m1.m_type == TASK_REPLY) ? m1.REP_STATUS : EFAULT);
954 if (sizes[0] != *sizep) {
955 printf("Filter: truncated reply from main driver\n");
957 /* If the driver returned a value *larger* than we requested,
958 * OR if we did NOT exceed the disk size, then we should
959 * report the driver for acting strangely!
961 if (sizes[0] < 0 || sizes[0] > *sizep ||
962 cmp64(add64u(pos, sizes[0]), disk_size) < 0)
963 return bad_driver(DRIVER_MAIN, BD_PROTO, EFAULT);
965 /* Return the actual size. */
966 *sizep = sizes[0];
969 if (both) {
970 if (m2.m_type != TASK_REPLY || m2.REP_STATUS != OK) {
971 printf("Filter: unexpected/invalid reply from "
972 "backup driver (%x, %d)\n",
973 m2.m_type, m2.REP_STATUS);
975 return bad_driver(DRIVER_BACKUP, BD_PROTO,
976 m2.m_type == TASK_REPLY ? m2.REP_STATUS :
977 EFAULT);
979 if (sizes[1] != *sizep) {
980 printf("Filter: truncated reply from backup driver\n");
982 /* As above */
983 if (sizes[1] < 0 || sizes[1] > *sizep ||
984 cmp64(add64u(pos, sizes[1]), disk_size) < 0)
985 return bad_driver(DRIVER_BACKUP, BD_PROTO,
986 EFAULT);
988 /* Return the actual size. */
989 if (*sizep >= sizes[1])
990 *sizep = sizes[1];
994 return OK;
997 /*===========================================================================*
998 * ds_event *
999 *===========================================================================*/
1000 void ds_event()
1002 char key[DS_MAX_KEYLEN];
1003 char *driver_prefix = "drv.vfs.";
1004 u32_t value;
1005 int type;
1006 endpoint_t owner_endpoint;
1007 int r;
1008 int which;
1010 /* Get the event and the owner from DS. */
1011 r = ds_check(key, &type, &owner_endpoint);
1012 if(r != OK) {
1013 if(r != ENOENT)
1014 printf("Filter: ds_event: ds_check failed: %d\n", r);
1015 return;
1017 r = ds_retrieve_u32(key, &value);
1018 if(r != OK) {
1019 printf("Filter: ds_event: ds_retrieve_u32 failed\n");
1020 return;
1023 /* Only check for VFS driver up events. */
1024 if(strncmp(key, driver_prefix, sizeof(driver_prefix))
1025 || value != DS_DRIVER_UP) {
1026 return;
1029 /* See if this is a driver we are responsible for. */
1030 if(driver[DRIVER_MAIN].endpt == owner_endpoint) {
1031 which = DRIVER_MAIN;
1033 else if(driver[DRIVER_BACKUP].endpt == owner_endpoint) {
1034 which = DRIVER_BACKUP;
1036 else {
1037 return;
1040 /* Mark the driver as (re)started. */
1041 driver[which].up_event = driver[which].up_event == UP_EXPECTED ?
1042 UP_NONE : UP_PENDING;