Datatype mappings are maintained in a separate hash table per datatype. The table must be initialized before applying an update, and freed when reversing the update, as shown in Figure 4-6. Figure 4-7 shows a set of new fields that should be added in the existing datatype definition of struct task_struct, the process control block in Linux 2.4. All these fields are grouped in a new datatype definition called struct new_task_struct, instead of extending the existing definition.
Figure 4-6. Managing a datatype mapping table.
/* Mapping table for the updated datatype of struct task_struct. */ dynreplace_access_t access_new_task_struct; void epckpt_init() { dynreplace_access_init(&access_new_task_struct); } void epckpt_cleanup() { dynreplace_access_cleanup(&access_new_task_struct); }
Figure 4-7. Definition of struct new_task_struct.
struct new_task_struct { int collect_ckpt_data:1; struct mmap_list *mmap_list; struct shmem_list *shmem_list; struct sem_list *sem_list; };
Figure 4-8. Creating a shadow variable in do_fork.
int do_fork_v2(unsigned long clone_flags, unsigned long stack_start, struct pt_regs *regs, unsigned long stack_size) { ... struct task_struct *p; void *new_p; ... dynreplace_access_lock(&access_new_task_struct); /* Create a shadow instance for this task_struct */ dynreplace_access_create(&access_new_task_struct, (void *)p, sizeof(struct new_task_struct)); /* Obtain a reference to the shadow instance */ new_p = dynreplace_access_find(&access_new_task_struct, (void *)p); /* Initialize the instance */ if (new_p != NULL) { /* Access the various fields */ dynreplace_access_field(struct new_task_struct, new_p, collect_ckpt_data) = 1; dynreplace_access_field(struct new_task_struct, new_p, mmap_list) = NULL; dynreplace_access_field(struct new_task_struct, new_p, shmem_list) = NULL; dynreplace_access_field(struct new_task_struct, new_p, sem_list) = NULL; /* Use the new fields to change control flow as required by the update. */ if (dynreplace_access_field(struct new_task_struct, new_p, collect_ckpt_data)) { /* Perform process checkpointing bookkeeping */ ... } } dynreplace_access_unlock(&access_new_task_struct); ... }
Figure 4-9. Freeing a shadow variable in do_exit.
ATTRIB_NORET NORET_TYPE void do_exit_v2(long code) { struct task_struct *tsk = current; ... { void *new_current; dynreplace_access_lock(&access_new_task_struct); new_current = dynreplace_access_find(&access_new_task_struct, (void *)current); if (new_current != NULL) dynreplace_access_remove(&access_new_task_struct, (void *)current); dynreplace_access_unlock(&access_new_task_struct); } ... }