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