1 #include "syslib.h" 2 #include <assert.h> 3 #include <minix/sysutil.h> 4 5 /* SEF Live update variables. */ 6 static int sef_lu_state; 7 8 /* SEF Live update callbacks. */ 9 static struct sef_cbs { 10 sef_cb_lu_prepare_t sef_cb_lu_prepare; 11 sef_cb_lu_state_isvalid_t sef_cb_lu_state_isvalid; 12 sef_cb_lu_state_changed_t sef_cb_lu_state_changed; 13 sef_cb_lu_state_dump_t sef_cb_lu_state_dump; 14 sef_cb_lu_state_save_t sef_cb_lu_state_save; 15 sef_cb_lu_response_t sef_cb_lu_response; 16 } sef_cbs = { 17 SEF_CB_LU_PREPARE_DEFAULT, 18 SEF_CB_LU_STATE_ISVALID_DEFAULT, 19 SEF_CB_LU_STATE_CHANGED_DEFAULT, 20 SEF_CB_LU_STATE_DUMP_DEFAULT, 21 SEF_CB_LU_STATE_SAVE_DEFAULT, 22 SEF_CB_LU_RESPONSE_DEFAULT 23 }; 24 25 /* SEF Live update prototypes for sef_receive(). */ 26 void do_sef_lu_before_receive(void); 27 int do_sef_lu_request(message *m_ptr); 28 29 /* SEF Live update helpers. */ 30 static void sef_lu_ready(int result); 31 32 /* Debug. */ 33 EXTERN char* sef_debug_header(void); 34 static int sef_lu_debug_cycle = 0; 35 36 /* Information about SELF. */ 37 EXTERN endpoint_t sef_self_endpoint; 38 EXTERN int sef_self_first_receive_done; 39 40 /*===========================================================================* 41 * do_sef_lu_before_receive * 42 *===========================================================================*/ 43 void do_sef_lu_before_receive(void) 44 { 45 /* Handle SEF Live update before receive events. */ 46 int r; 47 48 /* Initialize on first receive. */ 49 if(!sef_self_first_receive_done) { 50 sef_lu_state = SEF_LU_STATE_NULL; 51 } 52 53 /* Nothing to do if we are not preparing for a live update. */ 54 if(sef_lu_state == SEF_LU_STATE_NULL) { 55 return; 56 } 57 58 /* Debug. */ 59 #if SEF_LU_DEBUG 60 sef_lu_debug_cycle++; 61 sef_lu_debug_begin(); 62 sef_lu_dprint("%s, cycle=%d. Dumping state variables:\n", 63 sef_debug_header(), sef_lu_debug_cycle); 64 sef_cbs.sef_cb_lu_state_dump(sef_lu_state); 65 sef_lu_debug_end(); 66 #endif 67 68 /* Let the callback code handle the event. 69 * For SEF_LU_STATE_WORK_FREE, we're always ready, tell immediately. 70 */ 71 r = OK; 72 if(sef_lu_state != SEF_LU_STATE_WORK_FREE) { 73 r = sef_cbs.sef_cb_lu_prepare(sef_lu_state); 74 } 75 if(r == OK) { 76 sef_lu_ready(OK); 77 } 78 } 79 80 /*===========================================================================* 81 * do_sef_lu_request * 82 *===========================================================================*/ 83 int do_sef_lu_request(message *m_ptr) 84 { 85 /* Handle a SEF Live update request. */ 86 int state, old_state, is_valid_state; 87 88 sef_lu_debug_cycle = 0; 89 old_state = sef_lu_state; 90 state = m_ptr->m_rs_update.state; 91 92 /* Deal with prepare cancel requests first. */ 93 is_valid_state = (state == SEF_LU_STATE_NULL); 94 95 /* Otherwise only accept live update requests with a valid state. */ 96 is_valid_state = is_valid_state || sef_cbs.sef_cb_lu_state_isvalid(state); 97 if(!is_valid_state) { 98 if(sef_cbs.sef_cb_lu_state_isvalid == SEF_CB_LU_STATE_ISVALID_NULL) { 99 sef_lu_ready(ENOSYS); 100 } 101 else { 102 sef_lu_ready(EINVAL); 103 } 104 } 105 else { 106 /* Set the new live update state. */ 107 sef_lu_state = state; 108 109 /* If the live update state changed, let the callback code 110 * handle the rest. 111 */ 112 if(old_state != sef_lu_state) { 113 sef_cbs.sef_cb_lu_state_changed(old_state, sef_lu_state); 114 } 115 } 116 117 /* Return OK not to let anybody else intercept the request. */ 118 return(OK); 119 } 120 121 /*===========================================================================* 122 * sef_lu_ready * 123 *===========================================================================*/ 124 static void sef_lu_ready(int result) 125 { 126 message m; 127 int old_state, r; 128 129 #if SEF_LU_DEBUG 130 sef_lu_debug_begin(); 131 sef_lu_dprint("%s, cycle=%d. Ready to update with result: %d%s\n", 132 sef_debug_header(), sef_lu_debug_cycle, 133 result, (result == OK ? "(OK)" : "")); 134 sef_lu_debug_end(); 135 #endif 136 137 /* If result is OK, let the callback code save 138 * any state that must be carried over to the new version. 139 */ 140 if(result == OK) { 141 r = sef_cbs.sef_cb_lu_state_save(sef_lu_state); 142 if(r != OK) { 143 /* Abort update if callback returned error. */ 144 result = r; 145 } 146 } 147 148 /* Let the callback code produce a live update response and block. 149 * We should get beyond this point only if either result is an error or 150 * something else goes wrong in the callback code. 151 */ 152 m.m_source = sef_self_endpoint; 153 m.m_type = RS_LU_PREPARE; 154 m.m_rs_update.state = sef_lu_state; 155 m.m_rs_update.result = result; 156 r = sef_cbs.sef_cb_lu_response(&m); 157 158 #if SEF_LU_DEBUG 159 sef_lu_debug_begin(); 160 sef_lu_dprint("%s, cycle=%d. The %s aborted the update with result %d!\n", 161 sef_debug_header(), sef_lu_debug_cycle, 162 (result == OK ? "server" : "client"), 163 (result == OK ? r : result)); /* EINTR if update was canceled. */ 164 sef_lu_debug_end(); 165 #endif 166 167 /* Something went wrong. Update was aborted and we didn't get updated. 168 * Restore things back to normal and continue executing. 169 */ 170 old_state = sef_lu_state; 171 sef_lu_state = SEF_LU_STATE_NULL; 172 if(old_state != sef_lu_state) { 173 sef_cbs.sef_cb_lu_state_changed(old_state, sef_lu_state); 174 } 175 } 176 177 /*===========================================================================* 178 * sef_setcb_lu_prepare * 179 *===========================================================================*/ 180 void sef_setcb_lu_prepare(sef_cb_lu_prepare_t cb) 181 { 182 assert(cb != NULL); 183 sef_cbs.sef_cb_lu_prepare = cb; 184 } 185 186 /*===========================================================================* 187 * sef_setcb_lu_state_isvalid * 188 *===========================================================================*/ 189 void sef_setcb_lu_state_isvalid(sef_cb_lu_state_isvalid_t cb) 190 { 191 assert(cb != NULL); 192 sef_cbs.sef_cb_lu_state_isvalid = cb; 193 } 194 195 /*===========================================================================* 196 * sef_setcb_lu_state_changed * 197 *===========================================================================*/ 198 void sef_setcb_lu_state_changed(sef_cb_lu_state_changed_t cb) 199 { 200 assert(cb != NULL); 201 sef_cbs.sef_cb_lu_state_changed = cb; 202 } 203 204 /*===========================================================================* 205 * sef_setcb_lu_state_dump * 206 *===========================================================================*/ 207 void sef_setcb_lu_state_dump(sef_cb_lu_state_dump_t cb) 208 { 209 assert(cb != NULL); 210 sef_cbs.sef_cb_lu_state_dump = cb; 211 } 212 213 /*===========================================================================* 214 * sef_setcb_lu_state_save * 215 *===========================================================================*/ 216 void sef_setcb_lu_state_save(sef_cb_lu_state_save_t cb) 217 { 218 assert(cb != NULL); 219 sef_cbs.sef_cb_lu_state_save = cb; 220 } 221 222 /*===========================================================================* 223 * sef_setcb_lu_response * 224 *===========================================================================*/ 225 void sef_setcb_lu_response(sef_cb_lu_response_t cb) 226 { 227 assert(cb != NULL); 228 sef_cbs.sef_cb_lu_response = cb; 229 } 230 231 /*===========================================================================* 232 * sef_cb_lu_prepare_null * 233 *===========================================================================*/ 234 int sef_cb_lu_prepare_null(int UNUSED(state)) 235 { 236 return ENOTREADY; 237 } 238 239 /*===========================================================================* 240 * sef_cb_lu_state_isvalid_null * 241 *===========================================================================*/ 242 int sef_cb_lu_state_isvalid_null(int UNUSED(state)) 243 { 244 return FALSE; 245 } 246 247 /*===========================================================================* 248 * sef_cb_lu_state_changed_null * 249 *===========================================================================*/ 250 void sef_cb_lu_state_changed_null(int UNUSED(old_state), 251 int UNUSED(state)) 252 { 253 } 254 255 /*===========================================================================* 256 * sef_cb_lu_state_dump_null * 257 *===========================================================================*/ 258 void sef_cb_lu_state_dump_null(int UNUSED(state)) 259 { 260 sef_lu_dprint("NULL\n"); 261 } 262 263 /*===========================================================================* 264 * sef_cb_lu_state_save_null * 265 *===========================================================================*/ 266 int sef_cb_lu_state_save_null(int UNUSED(result)) 267 { 268 return OK; 269 } 270 271 /*===========================================================================* 272 * sef_cb_lu_response_null * 273 *===========================================================================*/ 274 int sef_cb_lu_response_null(message * UNUSED(m_ptr)) 275 { 276 return ENOSYS; 277 } 278 279 /*===========================================================================* 280 * sef_cb_lu_prepare_always_ready * 281 *===========================================================================*/ 282 int sef_cb_lu_prepare_always_ready(int UNUSED(state)) 283 { 284 return OK; 285 } 286 287 /*===========================================================================* 288 * sef_cb_lu_prepare_never_ready * 289 *===========================================================================*/ 290 int sef_cb_lu_prepare_never_ready(int UNUSED(state)) 291 { 292 #if SEF_LU_DEBUG 293 sef_lu_debug_begin(); 294 sef_lu_dprint("%s, cycle=%d. Simulating a service never ready to update...\n", 295 sef_debug_header(), sef_lu_debug_cycle); 296 sef_lu_debug_end(); 297 #endif 298 299 return ENOTREADY; 300 } 301 302 /*===========================================================================* 303 * sef_cb_lu_prepare_crash * 304 *===========================================================================*/ 305 int sef_cb_lu_prepare_crash(int UNUSED(state)) 306 { 307 panic("Simulating a crash at update prepare time..."); 308 309 return OK; 310 } 311 312 /*===========================================================================* 313 * sef_cb_lu_state_isvalid_standard * 314 *===========================================================================*/ 315 int sef_cb_lu_state_isvalid_standard(int state) 316 { 317 return SEF_LU_STATE_IS_STANDARD(state); 318 } 319 320 /*===========================================================================* 321 * sef_cb_lu_state_isvalid_workfree * 322 *===========================================================================*/ 323 int sef_cb_lu_state_isvalid_workfree(int state) 324 { 325 return (state == SEF_LU_STATE_WORK_FREE); 326 } 327 328 /*===========================================================================* 329 * sef_cb_lu_response_rs_reply * 330 *===========================================================================*/ 331 int sef_cb_lu_response_rs_reply(message *m_ptr) 332 { 333 int r; 334 335 /* Inform RS that we're ready with the given result. */ 336 r = ipc_sendrec(RS_PROC_NR, m_ptr); 337 if ( r != OK) { 338 return r; 339 } 340 341 return m_ptr->m_type == RS_LU_PREPARE ? EINTR : m_ptr->m_type; 342 } 343 344