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