vm: fix region reporting bug
[minix.git] / drivers / filter / driver.c
blobe5c16dcbe639bccd86adb639ce23d2a172a4af38
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 asynmsg_t amsgtable[2];
11 static int size_known = 0;
12 static u64_t disk_size;
14 static int problem_stats[BD_LAST] = { 0 };
16 /*===========================================================================*
17 * driver_open *
18 *===========================================================================*/
19 static int driver_open(int which)
21 /* Perform an open or close operation on the driver. This is
22 * unfinished code: we should never be doing a blocking sendrec() to
23 * the driver.
25 message msg;
26 cp_grant_id_t gid;
27 struct partition part;
28 sector_t sectors;
29 int r;
31 memset(&msg, 0, sizeof(msg));
32 msg.m_type = BDEV_OPEN;
33 msg.BDEV_MINOR = driver[which].minor;
34 msg.BDEV_ACCESS = R_BIT | W_BIT;
35 msg.BDEV_ID = 0;
36 r = sendrec(driver[which].endpt, &msg);
38 if (r != OK) {
39 /* Should we restart the driver now? */
40 printf("Filter: driver_open: sendrec returned %d\n", r);
42 return RET_REDO;
45 if(msg.m_type != BDEV_REPLY || msg.BDEV_STATUS != OK) {
46 printf("Filter: driver_open: sendrec returned %d, %d\n",
47 msg.m_type, msg.BDEV_STATUS);
49 return RET_REDO;
52 /* Take the opportunity to retrieve the hard disk size. */
53 gid = cpf_grant_direct(driver[which].endpt,
54 (vir_bytes) &part, sizeof(part), CPF_WRITE);
55 if(!GRANT_VALID(gid))
56 panic("invalid grant: %d", gid);
58 memset(&msg, 0, sizeof(msg));
59 msg.m_type = BDEV_IOCTL;
60 msg.BDEV_MINOR = driver[which].minor;
61 msg.BDEV_REQUEST = DIOCGETP;
62 msg.BDEV_GRANT = gid;
63 msg.BDEV_ID = 0;
65 r = sendrec(driver[which].endpt, &msg);
67 cpf_revoke(gid);
69 if (r != OK || msg.m_type != BDEV_REPLY || msg.BDEV_STATUS != OK) {
70 /* Not sure what to do here, either. */
71 printf("Filter: ioctl(DIOCGETP) returned (%d, %d)\n",
72 r, msg.m_type);
74 return RET_REDO;
77 if(!size_known) {
78 disk_size = part.size;
79 size_known = 1;
80 sectors = div64u(disk_size, SECTOR_SIZE);
81 if(cmp64(mul64u(sectors, SECTOR_SIZE), disk_size)) {
82 printf("Filter: partition too large\n");
84 return RET_REDO;
86 #if DEBUG
87 printf("Filter: partition size: 0x%"PRIx64" / %lu sectors\n",
88 disk_size, sectors);
89 #endif
90 } else {
91 if(cmp64(disk_size, part.size)) {
92 printf("Filter: partition size mismatch "
93 "(0x%"PRIx64" != 0x%"PRIx64")\n",
94 part.size, disk_size);
96 return RET_REDO;
100 return OK;
103 /*===========================================================================*
104 * driver_close *
105 *===========================================================================*/
106 static int driver_close(int which)
108 message msg;
109 int r;
111 memset(&msg, 0, sizeof(msg));
112 msg.m_type = BDEV_CLOSE;
113 msg.BDEV_MINOR = driver[which].minor;
114 msg.BDEV_ID = 0;
115 r = sendrec(driver[which].endpt, &msg);
117 if (r != OK) {
118 /* Should we restart the driver now? */
119 printf("Filter: driver_close: sendrec returned %d\n", r);
121 return RET_REDO;
124 if(msg.m_type != BDEV_REPLY || msg.BDEV_STATUS != OK) {
125 printf("Filter: driver_close: sendrec returned %d, %d\n",
126 msg.m_type, msg.BDEV_STATUS);
128 return RET_REDO;
131 return OK;
134 /*===========================================================================*
135 * driver_init *
136 *===========================================================================*/
137 void driver_init(void)
139 /* Initialize the driver layer. */
140 int r;
142 memset(driver, 0, sizeof(driver));
144 /* Endpoints unknown. */
145 driver[DRIVER_MAIN].endpt = NONE;
146 driver[DRIVER_BACKUP].endpt = NONE;
148 /* Get disk driver's and this proc's endpoint. */
149 driver[DRIVER_MAIN].label = MAIN_LABEL;
150 driver[DRIVER_MAIN].minor = MAIN_MINOR;
152 /* No up received yet but expected when the driver starts. */
153 driver[DRIVER_MAIN].up_event = UP_EXPECTED;
154 driver[DRIVER_BACKUP].up_event = UP_EXPECTED;
156 r = ds_retrieve_label_endpt(driver[DRIVER_MAIN].label,
157 &driver[DRIVER_MAIN].endpt);
158 if (r != OK) {
159 printf("Filter: failed to get main disk driver's endpoint: "
160 "%d\n", r);
161 bad_driver(DRIVER_MAIN, BD_DEAD, EFAULT);
162 check_driver(DRIVER_MAIN);
164 else if (driver_open(DRIVER_MAIN) != OK) {
165 panic("unhandled driver_open failure");
168 if(USE_MIRROR) {
169 driver[DRIVER_BACKUP].label = BACKUP_LABEL;
170 driver[DRIVER_BACKUP].minor = BACKUP_MINOR;
172 if(!strcmp(driver[DRIVER_MAIN].label,
173 driver[DRIVER_BACKUP].label)) {
174 panic("same driver: not tested");
177 r = ds_retrieve_label_endpt(driver[DRIVER_BACKUP].label,
178 &driver[DRIVER_BACKUP].endpt);
179 if (r != OK) {
180 printf("Filter: failed to get backup disk driver's "
181 "endpoint: %d\n", r);
182 bad_driver(DRIVER_BACKUP, BD_DEAD, EFAULT);
183 check_driver(DRIVER_BACKUP);
185 else if (driver_open(DRIVER_BACKUP) != OK) {
186 panic("unhandled driver_open failure");
191 /*===========================================================================*
192 * driver_shutdown *
193 *===========================================================================*/
194 void driver_shutdown(void)
196 /* Clean up. */
198 #if DEBUG
199 printf("Filter: %u driver deaths, %u protocol errors, "
200 "%u data errors\n", problem_stats[BD_DEAD],
201 problem_stats[BD_PROTO], problem_stats[BD_DATA]);
202 #endif
204 if(driver_close(DRIVER_MAIN) != OK)
205 printf("Filter: BDEV_CLOSE failed on shutdown (1)\n");
207 if(USE_MIRROR)
208 if(driver_close(DRIVER_BACKUP) != OK)
209 printf("Filter: BDEV_CLOSE failed on shutdown (2)\n");
212 /*===========================================================================*
213 * get_raw_size *
214 *===========================================================================*/
215 u64_t get_raw_size(void)
217 /* Return the size of the raw disks as used by the filter driver.
220 return disk_size;
223 /*===========================================================================*
224 * reset_kills *
225 *===========================================================================*/
226 void reset_kills(void)
228 /* Reset kill and retry statistics. */
229 driver[DRIVER_MAIN].kills = 0;
230 driver[DRIVER_MAIN].retries = 0;
231 driver[DRIVER_BACKUP].kills = 0;
232 driver[DRIVER_BACKUP].retries = 0;
235 /*===========================================================================*
236 * bad_driver *
237 *===========================================================================*/
238 int bad_driver(int which, int type, int error)
240 /* A disk driver has died or produced an error. Mark it so that we can
241 * deal with it later, and return RET_REDO to indicate that the
242 * current operation is to be retried. Also store an error code to
243 * return to the user if the situation is unrecoverable.
245 driver[which].problem = type;
246 driver[which].error = error;
248 return RET_REDO;
251 /*===========================================================================*
252 * new_driver_ep *
253 *===========================================================================*/
254 static int new_driver_ep(int which)
256 /* See if a new driver instance has already been started for the given
257 * driver, by retrieving its entry from DS.
259 int r;
260 endpoint_t endpt;
262 r = ds_retrieve_label_endpt(driver[which].label, &endpt);
264 if (r != OK) {
265 printf("Filter: DS query for %s failed\n",
266 driver[which].label);
268 return 0;
271 if (endpt == driver[which].endpt) {
272 #if DEBUG
273 printf("Filter: same endpoint for %s\n", driver[which].label);
274 #endif
275 return 0;
278 #if DEBUG
279 printf("Filter: new enpdoint for %s: %d -> %d\n", driver[which].label,
280 driver[which].endpt, endpt);
281 #endif
283 driver[which].endpt = endpt;
285 return 1;
288 /*===========================================================================*
289 * check_problem *
290 *===========================================================================*/
291 static int check_problem(int which, int problem, int retries, int *tell_rs)
293 /* A problem has occurred with a driver. Update statistics, and decide
294 * what to do. If EAGAIN is returned, the driver should be restarted;
295 * any other result will be passed up.
298 #if DEBUG
299 printf("Filter: check_problem processing driver %d, problem %d\n",
300 which, problem);
301 #endif
303 problem_stats[problem]++;
305 if(new_driver_ep(which)) {
306 #if DEBUG
307 printf("Filter: check_problem: noticed a new driver\n");
308 #endif
310 if(driver_open(which) == OK) {
311 #if DEBUG2
312 printf("Filter: open OK -> no recovery\n");
313 #endif
314 return OK;
315 } else {
316 #if DEBUG2
317 printf("Filter: open not OK -> recovery\n");
318 #endif
319 problem = BD_PROTO;
320 problem_stats[problem]++;
324 /* If the driver has died, we always need to restart it. If it has
325 * been giving problems, we first retry the request, up to N times,
326 * after which we kill and restart the driver. We restart the driver
327 * up to M times, after which we remove the driver from the mirror
328 * configuration. If we are not set up to do mirroring, we can only
329 * do one thing, and that is continue to limp along with the bad
330 * driver..
332 switch(problem) {
333 case BD_PROTO:
334 case BD_DATA:
335 driver[which].retries++;
337 #if DEBUG
338 printf("Filter: disk driver %d has had "
339 "%d/%d retry attempts, %d/%d kills\n", which,
340 driver[which].retries, NR_RETRIES,
341 driver[which].kills, NR_RESTARTS);
342 #endif
344 if (driver[which].retries < NR_RETRIES) {
345 if(retries == 1) {
346 #if DEBUG
347 printf("Filter: not restarting; retrying "
348 "(retries %d/%d, kills %d/%d)\n",
349 driver[which].retries, NR_RETRIES,
350 driver[which].kills, NR_RESTARTS);
351 #endif
352 return OK;
354 #if DEBUG
355 printf("Filter: restarting (retries %d/%d, "
356 "kills %d/%d, internal retry %d)\n",
357 driver[which].retries, NR_RETRIES,
358 driver[which].kills, NR_RESTARTS, retries);
359 #endif
362 #if DEBUG
363 printf("Filter: disk driver %d has reached error "
364 "threshold, restarting driver\n", which);
365 #endif
367 *tell_rs = (driver[which].up_event != UP_PENDING);
368 break;
370 case BD_DEAD:
371 /* Can't kill that which is already dead.. */
372 *tell_rs = 0;
373 break;
375 default:
376 panic("invalid problem: %d", problem);
379 /* At this point, the driver will be restarted. */
380 driver[which].retries = 0;
381 driver[which].kills++;
383 if (driver[which].kills < NR_RESTARTS)
384 return EAGAIN;
386 /* We've reached the maximum number of restarts for this driver. */
387 if (USE_MIRROR) {
388 printf("Filter: kill threshold reached, disabling mirroring\n");
390 USE_MIRROR = 0;
392 if (which == DRIVER_MAIN) {
393 driver[DRIVER_MAIN] = driver[DRIVER_BACKUP];
395 /* This is not necessary. */
396 strlcpy(MAIN_LABEL, BACKUP_LABEL, sizeof(MAIN_LABEL));
397 MAIN_MINOR = BACKUP_MINOR;
400 driver[DRIVER_BACKUP].endpt = NONE;
402 return OK;
404 else {
405 /* We tried, we really did. But now we give up. Tell the user.
407 printf("Filter: kill threshold reached, returning error\n");
409 if (driver[which].error == EAGAIN) return EIO;
411 return driver[which].error;
415 /*===========================================================================*
416 * restart_driver *
417 *===========================================================================*/
418 static void restart_driver(int which, int tell_rs)
420 /* Restart the given driver. Block until the new instance is up.
422 message msg;
423 int ipc_status;
424 int r;
426 if (tell_rs) {
427 /* Tell RS to refresh or restart the driver */
428 msg.m_type = RS_REFRESH;
429 msg.RS_CMD_ADDR = driver[which].label;
430 msg.RS_CMD_LEN = strlen(driver[which].label);
432 #if DEBUG
433 printf("Filter: asking RS to refresh %s..\n",
434 driver[which].label);
435 #endif
437 r = sendrec(RS_PROC_NR, &msg);
439 if (r != OK || msg.m_type != OK)
440 panic("RS request failed: %d", r);
442 #if DEBUG
443 printf("Filter: RS call succeeded\n");
444 #endif
447 /* Wait until the new driver instance is up, and get its endpoint. */
448 #if DEBUG
449 printf("Filter: endpoint update driver %d; old endpoint %d\n",
450 which, driver[which].endpt);
451 #endif
453 if(driver[which].up_event == UP_EXPECTED) {
454 driver[which].up_event = UP_NONE;
456 while(driver[which].up_event != UP_PENDING) {
457 r = driver_receive(DS_PROC_NR, &msg, &ipc_status);
458 if(r != OK)
459 panic("driver_receive returned error: %d", r);
461 ds_event();
465 /*===========================================================================*
466 * check_driver *
467 *===========================================================================*/
468 int check_driver(int which)
470 /* See if the given driver has been troublesome, and if so, deal with
471 * it.
473 int problem, tell_rs;
474 int r, retries = 0;
476 problem = driver[which].problem;
478 if (problem == BD_NONE)
479 return OK;
481 do {
482 if(retries) {
483 #if DEBUG
484 printf("Filter: check_driver: retry number %d\n",
485 retries);
486 #endif
487 problem = BD_PROTO;
489 retries++;
490 driver[which].problem = BD_NONE;
492 /* Decide what to do: continue operation, restart the driver,
493 * or return an error.
495 r = check_problem(which, problem, retries, &tell_rs);
496 if (r != EAGAIN)
497 return r;
499 /* Restarting the driver it is. First tell RS (if necessary),
500 * then wait for the new driver instance to come up.
502 restart_driver(which, tell_rs);
504 /* Finally, open the device on the new driver */
505 } while (driver_open(which) != OK);
507 #if DEBUG
508 printf("Filter: check_driver restarted driver %d, endpoint %d\n",
509 which, driver[which].endpt);
510 #endif
512 return OK;
515 /*===========================================================================*
516 * flt_senda *
517 *===========================================================================*/
518 static int flt_senda(message *mess, int which)
520 /* Send a message to one driver. Can only return OK at the moment. */
521 int r;
522 asynmsg_t *amp;
524 /* Fill in the last bits of the message. */
525 mess->BDEV_MINOR = driver[which].minor;
526 mess->BDEV_ID = 0;
528 /* Send the message asynchronously. */
529 amp = &amsgtable[which];
530 amp->dst = driver[which].endpt;
531 amp->msg = *mess;
532 amp->flags = AMF_VALID;
533 r = senda(amsgtable, 2);
535 if(r != OK)
536 panic("senda returned error: %d", r);
538 return r;
541 /*===========================================================================*
542 * check_senda *
543 *===========================================================================*/
544 static int check_senda(int which)
546 /* Check whether an earlier senda resulted in an error indicating the
547 * message never got delivered. Only in that case can we reliably say
548 * that the driver died. Return BD_DEAD in this case, and BD_PROTO
549 * otherwise.
551 asynmsg_t *amp;
553 amp = &amsgtable[which];
555 if ((amp->flags & AMF_DONE) && (amp->result == EDEADSRCDST)) {
557 return BD_DEAD;
560 return BD_PROTO;
563 /*===========================================================================*
564 * flt_receive *
565 *===========================================================================*/
566 static int flt_receive(message *mess, int which)
568 /* Receive a message from one or either driver, unless a timeout
569 * occurs. Can only return OK or RET_REDO.
571 int r;
572 int ipc_status;
574 for (;;) {
575 r = driver_receive(ANY, mess, &ipc_status);
576 if(r != OK)
577 panic("driver_receive returned error: %d", r);
579 if(mess->m_source == DS_PROC_NR && is_ipc_notify(ipc_status)) {
580 ds_event();
581 continue;
584 if(mess->m_source == CLOCK && is_ipc_notify(ipc_status)) {
585 if (mess->NOTIFY_TIMESTAMP < flt_alarm(-1)) {
586 #if DEBUG
587 printf("Filter: SKIPPING old alarm "
588 "notification\n");
589 #endif
590 continue;
593 #if DEBUG
594 printf("Filter: timeout waiting for disk driver %d "
595 "reply!\n", which);
596 #endif
598 /* If we're waiting for either driver,
599 * both are at fault.
601 if (which < 0) {
602 bad_driver(DRIVER_MAIN,
603 check_senda(DRIVER_MAIN), EFAULT);
605 return bad_driver(DRIVER_BACKUP,
606 check_senda(DRIVER_BACKUP), EFAULT);
609 /* Otherwise, just report the one not replying as dead.
611 return bad_driver(which, check_senda(which), EFAULT);
614 if (mess->m_source != driver[DRIVER_MAIN].endpt &&
615 mess->m_source != driver[DRIVER_BACKUP].endpt) {
616 #if DEBUG
617 printf("Filter: got STRAY message %d from %d\n",
618 mess->m_type, mess->m_source);
619 #endif
621 continue;
624 /* We are waiting for a reply from one specific driver. */
625 if (which >= 0) {
626 /* If the message source is that driver, good. */
627 if (mess->m_source == driver[which].endpt)
628 break;
630 /* This should probably be treated as a real protocol
631 * error. We do not abort any receives (not even paired
632 * receives) except because of timeouts. Getting here
633 * means a driver replied at least the timeout period
634 * later than expected, which should be enough reason
635 * to kill it really. The other explanation is that it
636 * is actually violating the protocol and sending bogus
637 * messages...
639 #if DEBUG
640 printf("Filter: got UNEXPECTED reply from %d\n",
641 mess->m_source);
642 #endif
644 continue;
647 /* We got a message from one of the drivers, and we didn't
648 * care which one we wanted to receive from. A-OK.
650 break;
653 return OK;
656 /*===========================================================================*
657 * flt_sendrec *
658 *===========================================================================*/
659 static int flt_sendrec(message *mess, int which)
661 int r;
663 r = flt_senda(mess, which);
664 if(r != OK)
665 return r;
667 if(check_senda(which) == BD_DEAD) {
668 return bad_driver(which, BD_DEAD, EFAULT);
671 /* Set alarm. */
672 flt_alarm(DRIVER_TIMEOUT);
674 r = flt_receive(mess, which);
676 /* Clear the alarm. */
677 flt_alarm(0);
678 return r;
681 /*===========================================================================*
682 * do_sendrec_both *
683 *===========================================================================*/
684 static int do_sendrec_both(message *m1, message *m2)
686 /* If USEE_MIRROR is set, call flt_sendrec() to both drivers.
687 * Otherwise, only call flt_sendrec() to the main driver.
688 * This function will only return either OK or RET_REDO.
690 int r, which = -1;
691 message ma, mb;
693 /* If the two disks use the same driver, call flt_sendrec() twice
694 * sequentially. Such a setup is not very useful though.
696 if (!strcmp(driver[DRIVER_MAIN].label, driver[DRIVER_BACKUP].label)) {
697 if ((r = flt_sendrec(m1, DRIVER_MAIN)) != OK) return r;
698 return flt_sendrec(m2, DRIVER_BACKUP);
701 /* If the two disks use different drivers, call flt_senda()
702 * twice, and then flt_receive(), and distinguish the return
703 * messages by means of m_source.
705 if ((r = flt_senda(m1, DRIVER_MAIN)) != OK) return r;
706 if ((r = flt_senda(m2, DRIVER_BACKUP)) != OK) return r;
708 /* Set alarm. */
709 flt_alarm(DRIVER_TIMEOUT);
711 /* The message received by the 1st flt_receive() may not be
712 * from DRIVER_MAIN.
714 if ((r = flt_receive(&ma, -1)) != OK) {
715 flt_alarm(0);
716 return r;
719 if (ma.m_source == driver[DRIVER_MAIN].endpt) {
720 which = DRIVER_BACKUP;
721 } else if (ma.m_source == driver[DRIVER_BACKUP].endpt) {
722 which = DRIVER_MAIN;
723 } else {
724 panic("message from unexpected source: %d",
725 ma.m_source);
728 r = flt_receive(&mb, which);
730 /* Clear the alarm. */
731 flt_alarm(0);
733 if(r != OK)
734 return r;
736 if (ma.m_source == driver[DRIVER_MAIN].endpt) {
737 *m1 = ma;
738 *m2 = mb;
739 } else {
740 *m1 = mb;
741 *m2 = ma;
744 return OK;
747 /*===========================================================================*
748 * do_sendrec_one *
749 *===========================================================================*/
750 static int do_sendrec_one(message *m1)
752 /* Only talk to the main driver. If something goes wrong, it will
753 * be fixed elsewhere.
754 * This function will only return either OK or RET_REDO.
757 return flt_sendrec(m1, DRIVER_MAIN);
760 /*===========================================================================*
761 * paired_sendrec *
762 *===========================================================================*/
763 static int paired_sendrec(message *m1, message *m2, int both)
765 /* Sendrec with the disk driver. If the disk driver is down, and was
766 * restarted, redo the request, until the driver works fine, or can't
767 * be restarted again.
769 int r;
771 #if DEBUG2
772 printf("paired_sendrec(%d) - <%d,%lx:%lx,%d> - %x,%x\n",
773 both, m1->m_type, m1->BDEV_POS_HI, m1->BDEV_POS_LO,
774 m1->BDEV_COUNT, m1->BDEV_GRANT, m2->BDEV_GRANT);
775 #endif
777 if (both)
778 r = do_sendrec_both(m1, m2);
779 else
780 r = do_sendrec_one(m1);
782 #if DEBUG2
783 if (r != OK)
784 printf("paired_sendrec about to return %d\n", r);
785 #endif
787 return r;
790 /*===========================================================================*
791 * single_grant *
792 *===========================================================================*/
793 static int single_grant(endpoint_t endpt, vir_bytes buf, int access,
794 cp_grant_id_t *gid, iovec_s_t vector[NR_IOREQS], size_t size)
796 /* Create grants for a vectored request to a single driver.
798 cp_grant_id_t grant;
799 size_t chunk;
800 int count;
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);
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 size,
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], size);
855 if (both) {
856 if(driver[DRIVER_BACKUP].endpt > 0) {
857 count = single_grant(driver[DRIVER_BACKUP].endpt,
858 (vir_bytes) buf2, access, &gids[1],
859 vectors[1], size);
862 return count;
865 /*===========================================================================*
866 * single_revoke *
867 *===========================================================================*/
868 static void single_revoke(cp_grant_id_t gid,
869 const iovec_s_t vector[NR_IOREQS], int count)
871 /* Revoke all grants associated with a request to a single driver.
872 * Modify the given size to reflect the actual I/O performed.
874 int i;
876 /* Revoke the grants for all the elements of the vector. */
877 for (i = 0; i < count; i++)
878 cpf_revoke(vector[i].iov_grant);
880 /* Then revoke the grant for the vector itself. */
881 cpf_revoke(gid);
884 /*===========================================================================*
885 * paired_revoke *
886 *===========================================================================*/
887 static void paired_revoke(const cp_grant_id_t *gids,
888 iovec_s_t vectors[2][NR_IOREQS], int count, int both)
890 /* Revoke grants to drivers for a single request.
893 single_revoke(gids[0], vectors[0], count);
895 if (both)
896 single_revoke(gids[1], vectors[1], count);
899 /*===========================================================================*
900 * read_write *
901 *===========================================================================*/
902 int read_write(u64_t pos, char *bufa, char *bufb, size_t *sizep, int request)
904 iovec_s_t vectors[2][NR_IOREQS];
905 message m1, m2;
906 cp_grant_id_t gids[2];
907 int r, both, count;
909 gids[0] = gids[1] = GRANT_INVALID;
911 /* Send two requests only if mirroring is enabled and the given request
912 * is either FLT_READ2 or FLT_WRITE.
914 both = (USE_MIRROR && request != FLT_READ);
916 count = paired_grant(bufa, bufb, request, gids, vectors, *sizep, both);
918 memset(&m1, 0, sizeof(m1));
919 m1.m_type = (request == FLT_WRITE) ? BDEV_SCATTER : BDEV_GATHER;
920 m1.BDEV_COUNT = count;
921 m1.BDEV_POS_LO = ex64lo(pos);
922 m1.BDEV_POS_HI = ex64hi(pos);
924 m2 = m1;
926 m1.BDEV_GRANT = gids[0];
927 m2.BDEV_GRANT = gids[1];
929 r = paired_sendrec(&m1, &m2, both);
931 paired_revoke(gids, vectors, count, both);
933 if(r != OK) {
934 #if DEBUG
935 if (r != RET_REDO)
936 printf("Filter: paired_sendrec returned %d\n", r);
937 #endif
938 return r;
941 if (m1.m_type != BDEV_REPLY || m1.BDEV_STATUS < 0) {
942 printf("Filter: unexpected/invalid reply from main driver: "
943 "(%x, %d)\n", m1.m_type, m1.BDEV_STATUS);
945 return bad_driver(DRIVER_MAIN, BD_PROTO,
946 (m1.m_type == BDEV_REPLY) ? m1.BDEV_STATUS : EFAULT);
949 if (m1.BDEV_STATUS != (ssize_t) *sizep) {
950 printf("Filter: truncated reply from main driver\n");
952 /* If the driver returned a value *larger* than we requested,
953 * OR if we did NOT exceed the disk size, then we should
954 * report the driver for acting strangely!
956 if (m1.BDEV_STATUS > (ssize_t) *sizep ||
957 cmp64(add64u(pos, m1.BDEV_STATUS), disk_size) < 0)
958 return bad_driver(DRIVER_MAIN, BD_PROTO, EFAULT);
960 /* Return the actual size. */
961 *sizep = m1.BDEV_STATUS;
964 if (both) {
965 if (m2.m_type != BDEV_REPLY || m2.BDEV_STATUS < 0) {
966 printf("Filter: unexpected/invalid reply from "
967 "backup driver (%x, %d)\n",
968 m2.m_type, m2.BDEV_STATUS);
970 return bad_driver(DRIVER_BACKUP, BD_PROTO,
971 m2.m_type == BDEV_REPLY ? m2.BDEV_STATUS :
972 EFAULT);
974 if (m2.BDEV_STATUS != (ssize_t) *sizep) {
975 printf("Filter: truncated reply from backup driver\n");
977 /* As above */
978 if (m2.BDEV_STATUS > (ssize_t) *sizep ||
979 cmp64(add64u(pos, m2.BDEV_STATUS),
980 disk_size) < 0)
981 return bad_driver(DRIVER_BACKUP, BD_PROTO,
982 EFAULT);
984 /* Return the actual size. */
985 if ((ssize_t) *sizep >= m2.BDEV_STATUS)
986 *sizep = m2.BDEV_STATUS;
990 return OK;
993 /*===========================================================================*
994 * ds_event *
995 *===========================================================================*/
996 void ds_event()
998 char key[DS_MAX_KEYLEN];
999 char *blkdriver_prefix = "drv.blk.";
1000 u32_t value;
1001 int type;
1002 endpoint_t owner_endpoint;
1003 int r;
1004 int which;
1006 /* Get the event and the owner from DS. */
1007 r = ds_check(key, &type, &owner_endpoint);
1008 if(r != OK) {
1009 if(r != ENOENT)
1010 printf("Filter: ds_event: ds_check failed: %d\n", r);
1011 return;
1013 r = ds_retrieve_u32(key, &value);
1014 if(r != OK) {
1015 printf("Filter: ds_event: ds_retrieve_u32 failed\n");
1016 return;
1019 /* Only check for VFS driver up events. */
1020 if(strncmp(key, blkdriver_prefix, strlen(blkdriver_prefix))
1021 || value != DS_DRIVER_UP) {
1022 return;
1025 /* See if this is a driver we are responsible for. */
1026 if(driver[DRIVER_MAIN].endpt == owner_endpoint) {
1027 which = DRIVER_MAIN;
1029 else if(driver[DRIVER_BACKUP].endpt == owner_endpoint) {
1030 which = DRIVER_BACKUP;
1032 else {
1033 return;
1036 /* Mark the driver as (re)started. */
1037 driver[which].up_event = driver[which].up_event == UP_EXPECTED ?
1038 UP_NONE : UP_PENDING;