<sys/socket.h>: turn off MSG_NOSIGNAL
[minix3.git] / drivers / filter / driver.c
blob2664df76a130e21e379753c2aa345bd795e38bd5
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 ipc_sendrec()
23 * to the driver.
25 message msg;
26 cp_grant_id_t gid;
27 struct part_geom 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 = BDEV_R_BIT | BDEV_W_BIT;
35 msg.BDEV_ID = 0;
36 r = ipc_sendrec(driver[which].endpt, &msg);
38 if (r != OK) {
39 /* Should we restart the driver now? */
40 printf("Filter: driver_open: ipc_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: ipc_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_USER = NONE;
64 msg.BDEV_ID = 0;
66 r = ipc_sendrec(driver[which].endpt, &msg);
68 cpf_revoke(gid);
70 if (r != OK || msg.m_type != BDEV_REPLY || msg.BDEV_STATUS != OK) {
71 /* Not sure what to do here, either. */
72 printf("Filter: ioctl(DIOCGETP) returned (%d, %d)\n",
73 r, msg.m_type);
75 return RET_REDO;
78 if(!size_known) {
79 disk_size = part.size;
80 size_known = 1;
81 sectors = (unsigned long)(disk_size / SECTOR_SIZE);
82 if ((u64_t)sectors * SECTOR_SIZE != disk_size) {
83 printf("Filter: partition too large\n");
85 return RET_REDO;
87 #if DEBUG
88 printf("Filter: partition size: 0x%"PRIx64" / %lu sectors\n",
89 disk_size, sectors);
90 #endif
91 } else {
92 if (disk_size != part.size) {
93 printf("Filter: partition size mismatch "
94 "(0x%"PRIx64" != 0x%"PRIx64")\n",
95 part.size, disk_size);
97 return RET_REDO;
101 return OK;
104 /*===========================================================================*
105 * driver_close *
106 *===========================================================================*/
107 static int driver_close(int which)
109 message msg;
110 int r;
112 memset(&msg, 0, sizeof(msg));
113 msg.m_type = BDEV_CLOSE;
114 msg.BDEV_MINOR = driver[which].minor;
115 msg.BDEV_ID = 0;
116 r = ipc_sendrec(driver[which].endpt, &msg);
118 if (r != OK) {
119 /* Should we restart the driver now? */
120 printf("Filter: driver_close: ipc_sendrec returned %d\n", r);
122 return RET_REDO;
125 if(msg.m_type != BDEV_REPLY || msg.BDEV_STATUS != OK) {
126 printf("Filter: driver_close: ipc_sendrec returned %d, %d\n",
127 msg.m_type, msg.BDEV_STATUS);
129 return RET_REDO;
132 return OK;
135 /*===========================================================================*
136 * driver_init *
137 *===========================================================================*/
138 void driver_init(void)
140 /* Initialize the driver layer. */
141 int r;
143 memset(driver, 0, sizeof(driver));
145 /* Endpoints unknown. */
146 driver[DRIVER_MAIN].endpt = NONE;
147 driver[DRIVER_BACKUP].endpt = NONE;
149 /* Get disk driver's and this proc's endpoint. */
150 driver[DRIVER_MAIN].label = MAIN_LABEL;
151 driver[DRIVER_MAIN].minor = MAIN_MINOR;
153 /* No up received yet but expected when the driver starts. */
154 driver[DRIVER_MAIN].up_event = UP_EXPECTED;
155 driver[DRIVER_BACKUP].up_event = UP_EXPECTED;
157 r = ds_retrieve_label_endpt(driver[DRIVER_MAIN].label,
158 &driver[DRIVER_MAIN].endpt);
159 if (r != OK) {
160 printf("Filter: failed to get main disk driver's endpoint: "
161 "%d\n", r);
162 bad_driver(DRIVER_MAIN, BD_DEAD, EFAULT);
163 check_driver(DRIVER_MAIN);
165 else if (driver_open(DRIVER_MAIN) != OK) {
166 panic("unhandled driver_open failure");
169 if(USE_MIRROR) {
170 driver[DRIVER_BACKUP].label = BACKUP_LABEL;
171 driver[DRIVER_BACKUP].minor = BACKUP_MINOR;
173 if(!strcmp(driver[DRIVER_MAIN].label,
174 driver[DRIVER_BACKUP].label)) {
175 panic("same driver: not tested");
178 r = ds_retrieve_label_endpt(driver[DRIVER_BACKUP].label,
179 &driver[DRIVER_BACKUP].endpt);
180 if (r != OK) {
181 printf("Filter: failed to get backup disk driver's "
182 "endpoint: %d\n", r);
183 bad_driver(DRIVER_BACKUP, BD_DEAD, EFAULT);
184 check_driver(DRIVER_BACKUP);
186 else if (driver_open(DRIVER_BACKUP) != OK) {
187 panic("unhandled driver_open failure");
192 /*===========================================================================*
193 * driver_shutdown *
194 *===========================================================================*/
195 void driver_shutdown(void)
197 /* Clean up. */
199 #if DEBUG
200 printf("Filter: %u driver deaths, %u protocol errors, "
201 "%u data errors\n", problem_stats[BD_DEAD],
202 problem_stats[BD_PROTO], problem_stats[BD_DATA]);
203 #endif
205 if(driver_close(DRIVER_MAIN) != OK)
206 printf("Filter: BDEV_CLOSE failed on shutdown (1)\n");
208 if(USE_MIRROR)
209 if(driver_close(DRIVER_BACKUP) != OK)
210 printf("Filter: BDEV_CLOSE failed on shutdown (2)\n");
213 /*===========================================================================*
214 * get_raw_size *
215 *===========================================================================*/
216 u64_t get_raw_size(void)
218 /* Return the size of the raw disks as used by the filter driver.
221 return disk_size;
224 /*===========================================================================*
225 * reset_kills *
226 *===========================================================================*/
227 void reset_kills(void)
229 /* Reset kill and retry statistics. */
230 driver[DRIVER_MAIN].kills = 0;
231 driver[DRIVER_MAIN].retries = 0;
232 driver[DRIVER_BACKUP].kills = 0;
233 driver[DRIVER_BACKUP].retries = 0;
236 /*===========================================================================*
237 * bad_driver *
238 *===========================================================================*/
239 int bad_driver(int which, int type, int error)
241 /* A disk driver has died or produced an error. Mark it so that we can
242 * deal with it later, and return RET_REDO to indicate that the
243 * current operation is to be retried. Also store an error code to
244 * return to the user if the situation is unrecoverable.
246 driver[which].problem = type;
247 driver[which].error = error;
249 return RET_REDO;
252 /*===========================================================================*
253 * new_driver_ep *
254 *===========================================================================*/
255 static int new_driver_ep(int which)
257 /* See if a new driver instance has already been started for the given
258 * driver, by retrieving its entry from DS.
260 int r;
261 endpoint_t endpt;
263 r = ds_retrieve_label_endpt(driver[which].label, &endpt);
265 if (r != OK) {
266 printf("Filter: DS query for %s failed\n",
267 driver[which].label);
269 return 0;
272 if (endpt == driver[which].endpt) {
273 #if DEBUG
274 printf("Filter: same endpoint for %s\n", driver[which].label);
275 #endif
276 return 0;
279 #if DEBUG
280 printf("Filter: new enpdoint for %s: %d -> %d\n", driver[which].label,
281 driver[which].endpt, endpt);
282 #endif
284 driver[which].endpt = endpt;
286 return 1;
289 /*===========================================================================*
290 * check_problem *
291 *===========================================================================*/
292 static int check_problem(int which, int problem, int retries, int *tell_rs)
294 /* A problem has occurred with a driver. Update statistics, and decide
295 * what to do. If EAGAIN is returned, the driver should be restarted;
296 * any other result will be passed up.
299 #if DEBUG
300 printf("Filter: check_problem processing driver %d, problem %d\n",
301 which, problem);
302 #endif
304 problem_stats[problem]++;
306 if(new_driver_ep(which)) {
307 #if DEBUG
308 printf("Filter: check_problem: noticed a new driver\n");
309 #endif
311 if(driver_open(which) == OK) {
312 #if DEBUG2
313 printf("Filter: open OK -> no recovery\n");
314 #endif
315 return OK;
316 } else {
317 #if DEBUG2
318 printf("Filter: open not OK -> recovery\n");
319 #endif
320 problem = BD_PROTO;
321 problem_stats[problem]++;
325 /* If the driver has died, we always need to restart it. If it has
326 * been giving problems, we first retry the request, up to N times,
327 * after which we kill and restart the driver. We restart the driver
328 * up to M times, after which we remove the driver from the mirror
329 * configuration. If we are not set up to do mirroring, we can only
330 * do one thing, and that is continue to limp along with the bad
331 * driver..
333 switch(problem) {
334 case BD_PROTO:
335 case BD_DATA:
336 driver[which].retries++;
338 #if DEBUG
339 printf("Filter: disk driver %d has had "
340 "%d/%d retry attempts, %d/%d kills\n", which,
341 driver[which].retries, NR_RETRIES,
342 driver[which].kills, NR_RESTARTS);
343 #endif
345 if (driver[which].retries < NR_RETRIES) {
346 if(retries == 1) {
347 #if DEBUG
348 printf("Filter: not restarting; retrying "
349 "(retries %d/%d, kills %d/%d)\n",
350 driver[which].retries, NR_RETRIES,
351 driver[which].kills, NR_RESTARTS);
352 #endif
353 return OK;
355 #if DEBUG
356 printf("Filter: restarting (retries %d/%d, "
357 "kills %d/%d, internal retry %d)\n",
358 driver[which].retries, NR_RETRIES,
359 driver[which].kills, NR_RESTARTS, retries);
360 #endif
363 #if DEBUG
364 printf("Filter: disk driver %d has reached error "
365 "threshold, restarting driver\n", which);
366 #endif
368 *tell_rs = (driver[which].up_event != UP_PENDING);
369 break;
371 case BD_DEAD:
372 /* Can't kill that which is already dead.. */
373 *tell_rs = 0;
374 break;
376 default:
377 panic("invalid problem: %d", problem);
380 /* At this point, the driver will be restarted. */
381 driver[which].retries = 0;
382 driver[which].kills++;
384 if (driver[which].kills < NR_RESTARTS)
385 return EAGAIN;
387 /* We've reached the maximum number of restarts for this driver. */
388 if (USE_MIRROR) {
389 printf("Filter: kill threshold reached, disabling mirroring\n");
391 USE_MIRROR = 0;
393 if (which == DRIVER_MAIN) {
394 driver[DRIVER_MAIN] = driver[DRIVER_BACKUP];
396 /* This is not necessary. */
397 strlcpy(MAIN_LABEL, BACKUP_LABEL, sizeof(MAIN_LABEL));
398 MAIN_MINOR = BACKUP_MINOR;
401 driver[DRIVER_BACKUP].endpt = NONE;
403 return OK;
405 else {
406 /* We tried, we really did. But now we give up. Tell the user.
408 printf("Filter: kill threshold reached, returning error\n");
410 if (driver[which].error == EAGAIN) return EIO;
412 return driver[which].error;
416 /*===========================================================================*
417 * restart_driver *
418 *===========================================================================*/
419 static void restart_driver(int which, int tell_rs)
421 /* Restart the given driver. Block until the new instance is up.
423 message msg;
424 int ipc_status;
425 int r;
427 if (tell_rs) {
428 /* Tell RS to refresh or restart the driver */
429 msg.m_type = RS_REFRESH;
430 msg.RS_CMD_ADDR = driver[which].label;
431 msg.RS_CMD_LEN = strlen(driver[which].label);
433 #if DEBUG
434 printf("Filter: asking RS to refresh %s..\n",
435 driver[which].label);
436 #endif
438 r = ipc_sendrec(RS_PROC_NR, &msg);
440 if (r != OK || msg.m_type != OK)
441 panic("RS request failed: %d", r);
443 #if DEBUG
444 printf("Filter: RS call succeeded\n");
445 #endif
448 /* Wait until the new driver instance is up, and get its endpoint. */
449 #if DEBUG
450 printf("Filter: endpoint update driver %d; old endpoint %d\n",
451 which, driver[which].endpt);
452 #endif
454 if(driver[which].up_event == UP_EXPECTED) {
455 driver[which].up_event = UP_NONE;
457 while(driver[which].up_event != UP_PENDING) {
458 r = driver_receive(DS_PROC_NR, &msg, &ipc_status);
459 if(r != OK)
460 panic("driver_receive returned error: %d", r);
462 ds_event();
466 /*===========================================================================*
467 * check_driver *
468 *===========================================================================*/
469 int check_driver(int which)
471 /* See if the given driver has been troublesome, and if so, deal with
472 * it.
474 int problem, tell_rs;
475 int r, retries = 0;
477 problem = driver[which].problem;
479 if (problem == BD_NONE)
480 return OK;
482 do {
483 if(retries) {
484 #if DEBUG
485 printf("Filter: check_driver: retry number %d\n",
486 retries);
487 #endif
488 problem = BD_PROTO;
490 retries++;
491 driver[which].problem = BD_NONE;
493 /* Decide what to do: continue operation, restart the driver,
494 * or return an error.
496 r = check_problem(which, problem, retries, &tell_rs);
497 if (r != EAGAIN)
498 return r;
500 /* Restarting the driver it is. First tell RS (if necessary),
501 * then wait for the new driver instance to come up.
503 restart_driver(which, tell_rs);
505 /* Finally, open the device on the new driver */
506 } while (driver_open(which) != OK);
508 #if DEBUG
509 printf("Filter: check_driver restarted driver %d, endpoint %d\n",
510 which, driver[which].endpt);
511 #endif
513 return OK;
516 /*===========================================================================*
517 * flt_senda *
518 *===========================================================================*/
519 static int flt_senda(message *mess, int which)
521 /* Send a message to one driver. Can only return OK at the moment. */
522 int r;
523 asynmsg_t *amp;
525 /* Fill in the last bits of the message. */
526 mess->BDEV_MINOR = driver[which].minor;
527 mess->BDEV_ID = 0;
529 /* Send the message asynchronously. */
530 amp = &amsgtable[which];
531 amp->dst = driver[which].endpt;
532 amp->msg = *mess;
533 amp->flags = AMF_VALID;
534 r = ipc_senda(amsgtable, 2);
536 if(r != OK)
537 panic("ipc_senda returned error: %d", r);
539 return r;
542 /*===========================================================================*
543 * check_senda *
544 *===========================================================================*/
545 static int check_senda(int which)
547 /* Check whether an earlier senda resulted in an error indicating the
548 * message never got delivered. Only in that case can we reliably say
549 * that the driver died. Return BD_DEAD in this case, and BD_PROTO
550 * otherwise.
552 asynmsg_t *amp;
554 amp = &amsgtable[which];
556 if ((amp->flags & AMF_DONE) && (amp->result == EDEADSRCDST)) {
558 return BD_DEAD;
561 return BD_PROTO;
564 /*===========================================================================*
565 * flt_receive *
566 *===========================================================================*/
567 static int flt_receive(message *mess, int which)
569 /* Receive a message from one or either driver, unless a timeout
570 * occurs. Can only return OK or RET_REDO.
572 int r;
573 int ipc_status;
575 for (;;) {
576 r = driver_receive(ANY, mess, &ipc_status);
577 if(r != OK)
578 panic("driver_receive returned error: %d", r);
580 if(mess->m_source == DS_PROC_NR && is_ipc_notify(ipc_status)) {
581 ds_event();
582 continue;
585 if(mess->m_source == CLOCK && is_ipc_notify(ipc_status)) {
586 if (mess->m_notify.timestamp < flt_alarm((clock_t) -1)) {
587 #if DEBUG
588 printf("Filter: SKIPPING old alarm "
589 "notification\n");
590 #endif
591 continue;
594 #if DEBUG
595 printf("Filter: timeout waiting for disk driver %d "
596 "reply!\n", which);
597 #endif
599 /* If we're waiting for either driver,
600 * both are at fault.
602 if (which < 0) {
603 bad_driver(DRIVER_MAIN,
604 check_senda(DRIVER_MAIN), EFAULT);
606 return bad_driver(DRIVER_BACKUP,
607 check_senda(DRIVER_BACKUP), EFAULT);
610 /* Otherwise, just report the one not replying as dead.
612 return bad_driver(which, check_senda(which), EFAULT);
615 if (mess->m_source != driver[DRIVER_MAIN].endpt &&
616 mess->m_source != driver[DRIVER_BACKUP].endpt) {
617 #if DEBUG
618 printf("Filter: got STRAY message %d from %d\n",
619 mess->m_type, mess->m_source);
620 #endif
622 continue;
625 /* We are waiting for a reply from one specific driver. */
626 if (which >= 0) {
627 /* If the message source is that driver, good. */
628 if (mess->m_source == driver[which].endpt)
629 break;
631 /* This should probably be treated as a real protocol
632 * error. We do not abort any receives (not even paired
633 * receives) except because of timeouts. Getting here
634 * means a driver replied at least the timeout period
635 * later than expected, which should be enough reason
636 * to kill it really. The other explanation is that it
637 * is actually violating the protocol and sending bogus
638 * messages...
640 #if DEBUG
641 printf("Filter: got UNEXPECTED reply from %d\n",
642 mess->m_source);
643 #endif
645 continue;
648 /* We got a message from one of the drivers, and we didn't
649 * care which one we wanted to receive from. A-OK.
651 break;
654 return OK;
657 /*===========================================================================*
658 * flt_sendrec *
659 *===========================================================================*/
660 static int flt_sendrec(message *mess, int which)
662 int r;
664 r = flt_senda(mess, which);
665 if(r != OK)
666 return r;
668 if(check_senda(which) == BD_DEAD) {
669 return bad_driver(which, BD_DEAD, EFAULT);
672 /* Set alarm. */
673 flt_alarm(DRIVER_TIMEOUT);
675 r = flt_receive(mess, which);
677 /* Clear the alarm. */
678 flt_alarm(0);
679 return r;
682 /*===========================================================================*
683 * do_sendrec_both *
684 *===========================================================================*/
685 static int do_sendrec_both(message *m1, message *m2)
687 /* If USEE_MIRROR is set, call flt_sendrec() to both drivers.
688 * Otherwise, only call flt_sendrec() to the main driver.
689 * This function will only return either OK or RET_REDO.
691 int r, which = -1;
692 message ma, mb;
694 /* If the two disks use the same driver, call flt_sendrec() twice
695 * sequentially. Such a setup is not very useful though.
697 if (!strcmp(driver[DRIVER_MAIN].label, driver[DRIVER_BACKUP].label)) {
698 if ((r = flt_sendrec(m1, DRIVER_MAIN)) != OK) return r;
699 return flt_sendrec(m2, DRIVER_BACKUP);
702 /* If the two disks use different drivers, call flt_senda()
703 * twice, and then flt_receive(), and distinguish the return
704 * messages by means of m_source.
706 if ((r = flt_senda(m1, DRIVER_MAIN)) != OK) return r;
707 if ((r = flt_senda(m2, DRIVER_BACKUP)) != OK) return r;
709 /* Set alarm. */
710 flt_alarm(DRIVER_TIMEOUT);
712 /* The message received by the 1st flt_receive() may not be
713 * from DRIVER_MAIN.
715 if ((r = flt_receive(&ma, -1)) != OK) {
716 flt_alarm(0);
717 return r;
720 if (ma.m_source == driver[DRIVER_MAIN].endpt) {
721 which = DRIVER_BACKUP;
722 } else if (ma.m_source == driver[DRIVER_BACKUP].endpt) {
723 which = DRIVER_MAIN;
724 } else {
725 panic("message from unexpected source: %d",
726 ma.m_source);
729 r = flt_receive(&mb, which);
731 /* Clear the alarm. */
732 flt_alarm(0);
734 if(r != OK)
735 return r;
737 if (ma.m_source == driver[DRIVER_MAIN].endpt) {
738 *m1 = ma;
739 *m2 = mb;
740 } else {
741 *m1 = mb;
742 *m2 = ma;
745 return OK;
748 /*===========================================================================*
749 * do_sendrec_one *
750 *===========================================================================*/
751 static int do_sendrec_one(message *m1)
753 /* Only talk to the main driver. If something goes wrong, it will
754 * be fixed elsewhere.
755 * This function will only return either OK or RET_REDO.
758 return flt_sendrec(m1, DRIVER_MAIN);
761 /*===========================================================================*
762 * paired_sendrec *
763 *===========================================================================*/
764 static int paired_sendrec(message *m1, message *m2, int both)
766 /* Sendrec with the disk driver. If the disk driver is down, and was
767 * restarted, redo the request, until the driver works fine, or can't
768 * be restarted again.
770 int r;
772 #if DEBUG2
773 printf("paired_sendrec(%d) - <%d,%llx,%d> - %x,%x\n",
774 both, m1->m_type, m1->BDEV_POS,
775 m1->BDEV_COUNT, m1->BDEV_GRANT, m2->BDEV_GRANT);
776 #endif
778 if (both)
779 r = do_sendrec_both(m1, m2);
780 else
781 r = do_sendrec_one(m1);
783 #if DEBUG2
784 if (r != OK)
785 printf("paired_sendrec about to return %d\n", r);
786 #endif
788 return r;
791 /*===========================================================================*
792 * single_grant *
793 *===========================================================================*/
794 static int single_grant(endpoint_t endpt, vir_bytes buf, int access,
795 cp_grant_id_t *gid, iovec_s_t vector[NR_IOREQS], size_t size)
797 /* Create grants for a vectored request to a single driver.
799 cp_grant_id_t grant;
800 size_t chunk;
801 int count;
803 /* Split up the request into chunks, if requested. This makes no
804 * difference at all, except that this works around a weird performance
805 * bug with large DMA PRDs on some machines.
807 if (CHUNK_SIZE > 0) chunk = CHUNK_SIZE;
808 else chunk = size;
810 /* Fill in the vector, creating a grant for each item. */
811 for (count = 0; size > 0 && count < NR_IOREQS; count++) {
812 /* The last chunk will contain all the remaining data. */
813 if (chunk > size || count == NR_IOREQS - 1)
814 chunk = size;
816 grant = cpf_grant_direct(endpt, buf, chunk, access);
817 if (!GRANT_VALID(grant))
818 panic("invalid grant: %d", grant);
820 vector[count].iov_grant = grant;
821 vector[count].iov_size = chunk;
823 buf += chunk;
824 size -= chunk;
827 /* Then create a grant for the vector itself. */
828 *gid = cpf_grant_direct(endpt, (vir_bytes) vector,
829 sizeof(vector[0]) * count, CPF_READ);
831 if (!GRANT_VALID(*gid))
832 panic("invalid grant: %d", *gid);
834 return count;
837 /*===========================================================================*
838 * paired_grant *
839 *===========================================================================*/
840 static int paired_grant(char *buf1, char *buf2, int request,
841 cp_grant_id_t *gids, iovec_s_t vectors[2][NR_IOREQS], size_t size,
842 int both)
844 /* Create memory grants, either to one or to both drivers.
846 int count, access;
848 count = 0;
849 access = (request == FLT_WRITE) ? CPF_READ : CPF_WRITE;
851 if(driver[DRIVER_MAIN].endpt > 0) {
852 count = single_grant(driver[DRIVER_MAIN].endpt,
853 (vir_bytes) buf1, access, &gids[0], vectors[0], size);
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], size);
863 return count;
866 /*===========================================================================*
867 * single_revoke *
868 *===========================================================================*/
869 static void single_revoke(cp_grant_id_t gid,
870 const iovec_s_t vector[NR_IOREQS], 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);
881 /* Then revoke the grant for the vector itself. */
882 cpf_revoke(gid);
885 /*===========================================================================*
886 * paired_revoke *
887 *===========================================================================*/
888 static void paired_revoke(const cp_grant_id_t *gids,
889 iovec_s_t vectors[2][NR_IOREQS], int count, int both)
891 /* Revoke grants to drivers for a single request.
894 single_revoke(gids[0], vectors[0], count);
896 if (both)
897 single_revoke(gids[1], vectors[1], count);
900 /*===========================================================================*
901 * read_write *
902 *===========================================================================*/
903 int read_write(u64_t pos, char *bufa, char *bufb, size_t *sizep, int request)
905 iovec_s_t vectors[2][NR_IOREQS];
906 message m1, m2;
907 cp_grant_id_t gids[2];
908 int r, both, count;
910 gids[0] = gids[1] = GRANT_INVALID;
912 /* Send two requests only if mirroring is enabled and the given request
913 * is either FLT_READ2 or FLT_WRITE.
915 both = (USE_MIRROR && request != FLT_READ);
917 count = paired_grant(bufa, bufb, request, gids, vectors, *sizep, both);
919 memset(&m1, 0, sizeof(m1));
920 m1.m_type = (request == FLT_WRITE) ? BDEV_SCATTER : BDEV_GATHER;
921 m1.BDEV_COUNT = count;
922 m1.BDEV_POS = 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 (pos + (unsigned int) m1.BDEV_STATUS < disk_size))
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 (pos + (unsigned int) m2.BDEV_STATUS <
980 disk_size))
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;