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);
}
...
}