Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

kexec: do a cleanup for function kexec_load

There are a lof of work to be done in function kexec_load, not only for
allocating structs and loading initram, but also for some misc.

To make it more clear, wrap a new function do_kexec_load which is used
to allocate structs and load initram. And the pre-work will be done in
kexec_load.

Signed-off-by: Minfei Huang <mnfhuang@gmail.com>
Cc: Vivek Goyal <vgoyal@redhat.com>
Cc: "Eric W. Biederman" <ebiederm@xmission.com>
Cc: Xunlei Pang <xlpang@redhat.com>
Cc: Baoquan He <bhe@redhat.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

authored by

Minfei Huang and committed by
Linus Torvalds
0eea0867 917a3560

+69 -56
+69 -56
kernel/kexec.c
··· 103 103 return ret; 104 104 } 105 105 106 + static int do_kexec_load(unsigned long entry, unsigned long nr_segments, 107 + struct kexec_segment __user *segments, unsigned long flags) 108 + { 109 + struct kimage **dest_image, *image; 110 + unsigned long i; 111 + int ret; 112 + 113 + if (flags & KEXEC_ON_CRASH) { 114 + dest_image = &kexec_crash_image; 115 + if (kexec_crash_image) 116 + arch_kexec_unprotect_crashkres(); 117 + } else { 118 + dest_image = &kexec_image; 119 + } 120 + 121 + if (nr_segments == 0) { 122 + /* Uninstall image */ 123 + kimage_free(xchg(dest_image, NULL)); 124 + return 0; 125 + } 126 + if (flags & KEXEC_ON_CRASH) { 127 + /* 128 + * Loading another kernel to switch to if this one 129 + * crashes. Free any current crash dump kernel before 130 + * we corrupt it. 131 + */ 132 + kimage_free(xchg(&kexec_crash_image, NULL)); 133 + } 134 + 135 + ret = kimage_alloc_init(&image, entry, nr_segments, segments, flags); 136 + if (ret) 137 + return ret; 138 + 139 + if (flags & KEXEC_ON_CRASH) 140 + crash_map_reserved_pages(); 141 + 142 + if (flags & KEXEC_PRESERVE_CONTEXT) 143 + image->preserve_context = 1; 144 + 145 + ret = machine_kexec_prepare(image); 146 + if (ret) 147 + goto out; 148 + 149 + for (i = 0; i < nr_segments; i++) { 150 + ret = kimage_load_segment(image, &image->segment[i]); 151 + if (ret) 152 + goto out; 153 + } 154 + 155 + kimage_terminate(image); 156 + 157 + /* Install the new kernel and uninstall the old */ 158 + image = xchg(dest_image, image); 159 + 160 + out: 161 + if ((flags & KEXEC_ON_CRASH) && kexec_crash_image) 162 + arch_kexec_protect_crashkres(); 163 + 164 + /* 165 + * Once the reserved memory is mapped, we should unmap this memory 166 + * before returning 167 + */ 168 + if (flags & KEXEC_ON_CRASH) 169 + crash_unmap_reserved_pages(); 170 + kimage_free(image); 171 + return ret; 172 + } 173 + 106 174 /* 107 175 * Exec Kernel system call: for obvious reasons only root may call it. 108 176 * ··· 195 127 SYSCALL_DEFINE4(kexec_load, unsigned long, entry, unsigned long, nr_segments, 196 128 struct kexec_segment __user *, segments, unsigned long, flags) 197 129 { 198 - struct kimage **dest_image, *image; 199 130 int result; 200 131 201 132 /* We only trust the superuser with rebooting the system. */ ··· 219 152 if (nr_segments > KEXEC_SEGMENT_MAX) 220 153 return -EINVAL; 221 154 222 - image = NULL; 223 - result = 0; 224 - 225 155 /* Because we write directly to the reserved memory 226 156 * region when loading crash kernels we need a mutex here to 227 157 * prevent multiple crash kernels from attempting to load ··· 230 166 if (!mutex_trylock(&kexec_mutex)) 231 167 return -EBUSY; 232 168 233 - dest_image = &kexec_image; 234 - if (flags & KEXEC_ON_CRASH) { 235 - dest_image = &kexec_crash_image; 236 - if (kexec_crash_image) 237 - arch_kexec_unprotect_crashkres(); 238 - } 169 + result = do_kexec_load(entry, nr_segments, segments, flags); 239 170 240 - if (nr_segments > 0) { 241 - unsigned long i; 242 - 243 - if (flags & KEXEC_ON_CRASH) { 244 - /* 245 - * Loading another kernel to switch to if this one 246 - * crashes. Free any current crash dump kernel before 247 - * we corrupt it. 248 - */ 249 - 250 - kimage_free(xchg(&kexec_crash_image, NULL)); 251 - result = kimage_alloc_init(&image, entry, nr_segments, 252 - segments, flags); 253 - crash_map_reserved_pages(); 254 - } else { 255 - /* Loading another kernel to reboot into. */ 256 - 257 - result = kimage_alloc_init(&image, entry, nr_segments, 258 - segments, flags); 259 - } 260 - if (result) 261 - goto unmap_page; 262 - 263 - if (flags & KEXEC_PRESERVE_CONTEXT) 264 - image->preserve_context = 1; 265 - result = machine_kexec_prepare(image); 266 - if (result) 267 - goto unmap_page; 268 - 269 - for (i = 0; i < nr_segments; i++) { 270 - result = kimage_load_segment(image, &image->segment[i]); 271 - if (result) 272 - goto unmap_page; 273 - } 274 - kimage_terminate(image); 275 - unmap_page: 276 - if (flags & KEXEC_ON_CRASH) 277 - crash_unmap_reserved_pages(); 278 - if (result) 279 - goto out; 280 - } 281 - /* Install the new kernel, and Uninstall the old */ 282 - image = xchg(dest_image, image); 283 - 284 - out: 285 171 if ((flags & KEXEC_ON_CRASH) && kexec_crash_image) 286 172 arch_kexec_protect_crashkres(); 287 173 288 174 mutex_unlock(&kexec_mutex); 289 - kimage_free(image); 290 175 291 176 return result; 292 177 }