]> Zhao Yanbai Git Server - minix.git/commitdiff
blocktest: support for stateless driver restarts
authorDavid van Moolenbroek <david@minix3.org>
Sun, 11 Dec 2011 18:27:23 +0000 (19:27 +0100)
committerDavid van Moolenbroek <david@minix3.org>
Sun, 11 Dec 2011 21:41:51 +0000 (22:41 +0100)
test/blocktest/blocktest.c

index 19176be90fda29ca897b551a88f001b4c4a801fa..055d8040ae27a39a9e0ab21655b707b85c288200 100644 (file)
@@ -9,6 +9,7 @@
 
 enum {
        RESULT_OK,                      /* exactly as expected */
+       RESULT_DEATH,                   /* driver died */
        RESULT_COMMFAIL,                /* communication failed */
        RESULT_BADTYPE,                 /* bad type in message */
        RESULT_BADID,                   /* bad request ID in message */
@@ -94,6 +95,9 @@ PRIVATE void got_result(result_t *res, char *desc)
                (res->type == RESULT_OK) ? "PASS" : "FAIL");
 
        switch (res->type) {
+       case RESULT_DEATH:
+               printf("- driver died\n");
+               break;
        case RESULT_COMMFAIL:
                printf("- communication failed; sendrec returned %d\n",
                        res->value);
@@ -159,47 +163,52 @@ PRIVATE int sendrec_driver(message *m_ptr, ssize_t exp, result_t *res)
 {
        /* Make a call to the driver, and perform basic checks on the return
         * message. Fill in the result structure, wiping out what was in there
-        * before. If the driver reports being restarted, reopen all previously
-        * opened devices and retry the call.
+        * before. If the driver dies in the process, attempt to recover but
+        * fail the request.
         */
        message m_orig;
-       int i, r, retry;
+       endpoint_t last_endpt;
+       int i, r;
 
        m_orig = *m_ptr;
-       retry = 0;
-
-       do {
-               r = sendrec(driver_endpt, m_ptr);
-
-               if (r != OK)
-                       return set_result(res, RESULT_COMMFAIL, r);
 
-               if (m_ptr->m_type != BDEV_REPLY)
-                       return set_result(res, RESULT_BADTYPE, m_ptr->m_type);
+       r = sendrec(driver_endpt, m_ptr);
 
-               if (m_ptr->BDEV_ID != m_orig.BDEV_ID)
-                       return set_result(res, RESULT_BADID, m_ptr->BDEV_ID);
-
-               if (m_ptr->BDEV_STATUS != ERESTART) break;
-
-               /* The driver has died. Reopen all devices that we opened
-                * earlier, and resend the request. Up to three times.
+       if (r == EDEADSRCDST) {
+               /* The driver has died. Find its new endpoint, and reopen all
+                * devices that we opened earlier. Then return failure.
                 */
                printf("WARNING: driver has died, attempting to proceed\n");
 
                driver_deaths++;
 
+               /* Keep trying until we get a new endpoint. */
+               last_endpt = driver_endpt;
+               for (;;) {
+                       r = ds_retrieve_label_endpt(driver_label,
+                               &driver_endpt);
+
+                       if (r == OK && last_endpt != driver_endpt)
+                               break;
+
+                       micro_delay(100000);
+               }
+
                for (i = 0; i < nr_opened; i++)
                        reopen_device(opened[i]);
 
-               *m_ptr = m_orig;
-       } while (++retry < 3);
-
-       if (retry == 3) {
-               printf("FATAL: driver has died three times in a row\n");
-               exit(1);
+               return set_result(res, RESULT_DEATH, 0);
        }
 
+       if (r != OK)
+               return set_result(res, RESULT_COMMFAIL, r);
+
+       if (m_ptr->m_type != BDEV_REPLY)
+               return set_result(res, RESULT_BADTYPE, m_ptr->m_type);
+
+       if (m_ptr->BDEV_ID != m_orig.BDEV_ID)
+               return set_result(res, RESULT_BADID, m_ptr->BDEV_ID);
+
        if ((exp < 0 && m_ptr->BDEV_STATUS >= 0) ||
                        (exp >= 0 && m_ptr->BDEV_STATUS < 0))
                return set_result(res, RESULT_BADSTATUS, m_ptr->BDEV_STATUS);