xref: /minix/minix/lib/libblockdriver/liveupdate.c (revision 0a6a1f1d)
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  *===========================================================================*/
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  *===========================================================================*/
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  *===========================================================================*/
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  *===========================================================================*/
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