1 /* This file implements SEF hooks for live update of multithreaded block
2 * drivers.
3 */
4
5 #include <minix/drivers.h>
6 #include <minix/blockdriver_mt.h>
7
8 #include "driver_mt.h"
9
10 /*===========================================================================*
11 * sef_cb_lu_prepare *
12 *===========================================================================*/
sef_cb_lu_prepare(int state)13 static int sef_cb_lu_prepare(int state)
14 {
15 /* This function is called to decide whether we can enter the given live
16 * update state, and to prepare for such an update. If we are requested to
17 * update to a request-free or protocol-free state, make sure there is no work
18 * pending or being processed, and shut down all worker threads.
19 */
20
21 switch (state) {
22 case SEF_LU_STATE_REQUEST_FREE:
23 case SEF_LU_STATE_PROTOCOL_FREE:
24 if (!blockdriver_mt_is_idle()) {
25 printf("libblockdriver(%d): not idle, blocking update\n",
26 sef_self());
27 break;
28 }
29
30 blockdriver_mt_suspend();
31
32 return OK;
33 }
34
35 return ENOTREADY;
36 }
37
38 /*===========================================================================*
39 * sef_cb_lu_state_changed *
40 *===========================================================================*/
sef_cb_lu_state_changed(int old_state,int state)41 static void sef_cb_lu_state_changed(int old_state, int state)
42 {
43 /* This function is called in the old driver instance when the state changes.
44 * We use it to resume normal operation after a failed live update.
45 */
46
47 if (state != SEF_LU_STATE_NULL)
48 return;
49
50 switch (old_state) {
51 case SEF_LU_STATE_REQUEST_FREE:
52 case SEF_LU_STATE_PROTOCOL_FREE:
53 blockdriver_mt_resume();
54 }
55 }
56
57 /*===========================================================================*
58 * sef_cb_init_lu *
59 *===========================================================================*/
sef_cb_init_lu(int type,sef_init_info_t * info)60 static int sef_cb_init_lu(int type, sef_init_info_t *info)
61 {
62 /* This function is called in the new driver instance during a live update.
63 */
64 int r;
65
66 /* Perform regular state transfer. */
67 if ((r = SEF_CB_INIT_LU_DEFAULT(type, info)) != OK)
68 return r;
69
70 /* Recreate worker threads, if necessary. */
71 switch (info->prepare_state) {
72 case SEF_LU_STATE_REQUEST_FREE:
73 case SEF_LU_STATE_PROTOCOL_FREE:
74 blockdriver_mt_resume();
75 }
76
77 return OK;
78 }
79
80 /*===========================================================================*
81 * blockdriver_mt_support_lu *
82 *===========================================================================*/
blockdriver_mt_support_lu(void)83 void blockdriver_mt_support_lu(void)
84 {
85 /* Enable suppor for live update of this driver. To be called before
86 * sef_startup().
87 */
88
89 /* Register live update callbacks. */
90 sef_setcb_init_lu(sef_cb_init_lu);
91 sef_setcb_lu_prepare(sef_cb_lu_prepare);
92 sef_setcb_lu_state_changed(sef_cb_lu_state_changed);
93 sef_setcb_lu_state_isvalid(sef_cb_lu_state_isvalid_standard);
94 }
95