diff --git a/include/linux/pin_mem.h b/include/linux/pin_mem.h index b01cd05ace061d8af99868152e4cd7fe6913966e..6c54482a42a11b36ca100b874fddf7e4ec159b12 100644 --- a/include/linux/pin_mem.h +++ b/include/linux/pin_mem.h @@ -89,5 +89,11 @@ extern struct resource pin_memory_resource; #endif extern void init_reserve_page_map(unsigned long map_addr, unsigned long map_size); +#ifdef CONFIG_PID_RESERVE +extern bool is_need_reserve_pids(void); +extern void free_reserved_pid(struct idr *idr, int pid); +extern void reserve_pids(struct idr *idr, int pid_max); +#endif + #endif /* CONFIG_PIN_MEMORY */ #endif /* _LINUX_PIN_MEMORY_H */ diff --git a/kernel/pid.c b/kernel/pid.c index 0b90596f9f125cd944e89da542b4b2af845a93a8..be2ec1d26896ebf13ad05481fa751a09261b9999 100644 --- a/kernel/pid.c +++ b/kernel/pid.c @@ -44,6 +44,9 @@ #include #include #include +#ifdef CONFIG_PID_RESERVE +#include +#endif struct pid init_struct_pid = { .count = REFCOUNT_INIT(1), @@ -209,6 +212,9 @@ struct pid *alloc_pid(struct pid_namespace *ns, pid_t *set_tid, spin_lock_irq(&pidmap_lock); if (tid) { +#ifdef CONFIG_PID_RESERVE + free_reserved_pid(&tmp->idr, tid); +#endif nr = idr_alloc(&tmp->idr, NULL, tid, tid + 1, GFP_ATOMIC); /* @@ -622,6 +628,10 @@ void __init pid_idr_init(void) init_pid_ns.pid_cachep = KMEM_CACHE(pid, SLAB_HWCACHE_ALIGN | SLAB_PANIC | SLAB_ACCOUNT); +#ifdef CONFIG_PID_RESERVE + if (is_need_reserve_pids()) + reserve_pids(&init_pid_ns.idr, pid_max); +#endif } static struct file *__pidfd_fget(struct task_struct *task, int fd) diff --git a/mm/Kconfig b/mm/Kconfig index 15eebc24d7036432dc3729568b65e12f15132cbd..8d1f074b615b222050faac674f5bf83304dbe619 100644 --- a/mm/Kconfig +++ b/mm/Kconfig @@ -906,4 +906,14 @@ config PIN_MEMORY and restore. We can pin the memory data of tasks and collect the corresponding physical pages mapping info in checkpoint, and remap the physical pages to restore tasks in restore. + +config PID_RESERVE + bool "Support for reserve pid" + depends on PIN_MEMORY + help + Say y here to enable the pid reserved feature for checkpoint. + and restore. + We record the pid of dump task in the reserve memory, + and reserve the pids before init task start. In restore process, + free the reserved pids and realloc them for use. endmenu diff --git a/mm/pin_mem.c b/mm/pin_mem.c index df618ba1f5bb1a6574d3dcab44c422e6ef683b71..3fd3638a89e3b0c8a780729d56a642baf8698fe1 100644 --- a/mm/pin_mem.c +++ b/mm/pin_mem.c @@ -1088,4 +1088,55 @@ void clear_pin_memory_record(void) } EXPORT_SYMBOL_GPL(clear_pin_memory_record); +#ifdef CONFIG_PID_RESERVE +struct idr *reserve_idr; + +/* test if there exist pin memory tasks */ +bool is_need_reserve_pids(void) +{ + return (pin_pid_num > 0); +} + +void free_reserved_pid(struct idr *idr, int pid) +{ + unsigned int index; + struct page_map_info *pmi; + + if (!max_pin_pid_num || idr != reserve_idr) + return; + + for (index = 0; index < pin_pid_num; index++) { + pmi = &(user_space_reserve_start[index]); + if (pmi->pid == pid && pmi->pid_reserved) { + idr_remove(idr, pid); + return; + } + } +} + +/* reserve pids for check point tasks which pinned memory */ +void reserve_pids(struct idr *idr, int pid_max) +{ + int alloc_pid; + unsigned int index; + struct page_map_info *pmi; + + if (!max_pin_pid_num) + return; + reserve_idr = idr; + for (index = 0; index < pin_pid_num; index++) { + pmi = &(user_space_reserve_start[index]); + pmi->pid_reserved = true; + alloc_pid = idr_alloc(idr, NULL, pmi->pid, pid_max, GFP_ATOMIC); + if (alloc_pid != pmi->pid) { + if (alloc_pid > 0) + idr_remove(idr, alloc_pid); + pr_warn("Reserve pid (%d) fail, real pid is %d.\n", alloc_pid, pmi->pid); + pmi->pid_reserved = false; + continue; + } + } +} +#endif /* CONFIG_PID_RESERVE */ + #endif /* CONFIG_PIN_MEMORY */