diff options
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/kexec.c | 34 |
1 files changed, 10 insertions, 24 deletions
diff --git a/kernel/kexec.c b/kernel/kexec.c index 9fc6f7cbd8a8..59f3f0df35d4 100644 --- a/kernel/kexec.c +++ b/kernel/kexec.c | |||
@@ -12,7 +12,7 @@ | |||
12 | #include <linux/slab.h> | 12 | #include <linux/slab.h> |
13 | #include <linux/fs.h> | 13 | #include <linux/fs.h> |
14 | #include <linux/kexec.h> | 14 | #include <linux/kexec.h> |
15 | #include <linux/spinlock.h> | 15 | #include <linux/mutex.h> |
16 | #include <linux/list.h> | 16 | #include <linux/list.h> |
17 | #include <linux/highmem.h> | 17 | #include <linux/highmem.h> |
18 | #include <linux/syscalls.h> | 18 | #include <linux/syscalls.h> |
@@ -924,19 +924,14 @@ static int kimage_load_segment(struct kimage *image, | |||
924 | */ | 924 | */ |
925 | struct kimage *kexec_image; | 925 | struct kimage *kexec_image; |
926 | struct kimage *kexec_crash_image; | 926 | struct kimage *kexec_crash_image; |
927 | /* | 927 | |
928 | * A home grown binary mutex. | 928 | static DEFINE_MUTEX(kexec_mutex); |
929 | * Nothing can wait so this mutex is safe to use | ||
930 | * in interrupt context :) | ||
931 | */ | ||
932 | static int kexec_lock; | ||
933 | 929 | ||
934 | asmlinkage long sys_kexec_load(unsigned long entry, unsigned long nr_segments, | 930 | asmlinkage long sys_kexec_load(unsigned long entry, unsigned long nr_segments, |
935 | struct kexec_segment __user *segments, | 931 | struct kexec_segment __user *segments, |
936 | unsigned long flags) | 932 | unsigned long flags) |
937 | { | 933 | { |
938 | struct kimage **dest_image, *image; | 934 | struct kimage **dest_image, *image; |
939 | int locked; | ||
940 | int result; | 935 | int result; |
941 | 936 | ||
942 | /* We only trust the superuser with rebooting the system. */ | 937 | /* We only trust the superuser with rebooting the system. */ |
@@ -972,8 +967,7 @@ asmlinkage long sys_kexec_load(unsigned long entry, unsigned long nr_segments, | |||
972 | * | 967 | * |
973 | * KISS: always take the mutex. | 968 | * KISS: always take the mutex. |
974 | */ | 969 | */ |
975 | locked = xchg(&kexec_lock, 1); | 970 | if (!mutex_trylock(&kexec_mutex)) |
976 | if (locked) | ||
977 | return -EBUSY; | 971 | return -EBUSY; |
978 | 972 | ||
979 | dest_image = &kexec_image; | 973 | dest_image = &kexec_image; |
@@ -1015,8 +1009,7 @@ asmlinkage long sys_kexec_load(unsigned long entry, unsigned long nr_segments, | |||
1015 | image = xchg(dest_image, image); | 1009 | image = xchg(dest_image, image); |
1016 | 1010 | ||
1017 | out: | 1011 | out: |
1018 | locked = xchg(&kexec_lock, 0); /* Release the mutex */ | 1012 | mutex_unlock(&kexec_mutex); |
1019 | BUG_ON(!locked); | ||
1020 | kimage_free(image); | 1013 | kimage_free(image); |
1021 | 1014 | ||
1022 | return result; | 1015 | return result; |
@@ -1063,10 +1056,7 @@ asmlinkage long compat_sys_kexec_load(unsigned long entry, | |||
1063 | 1056 | ||
1064 | void crash_kexec(struct pt_regs *regs) | 1057 | void crash_kexec(struct pt_regs *regs) |
1065 | { | 1058 | { |
1066 | int locked; | 1059 | /* Take the kexec_mutex here to prevent sys_kexec_load |
1067 | |||
1068 | |||
1069 | /* Take the kexec_lock here to prevent sys_kexec_load | ||
1070 | * running on one cpu from replacing the crash kernel | 1060 | * running on one cpu from replacing the crash kernel |
1071 | * we are using after a panic on a different cpu. | 1061 | * we are using after a panic on a different cpu. |
1072 | * | 1062 | * |
@@ -1074,8 +1064,7 @@ void crash_kexec(struct pt_regs *regs) | |||
1074 | * of memory the xchg(&kexec_crash_image) would be | 1064 | * of memory the xchg(&kexec_crash_image) would be |
1075 | * sufficient. But since I reuse the memory... | 1065 | * sufficient. But since I reuse the memory... |
1076 | */ | 1066 | */ |
1077 | locked = xchg(&kexec_lock, 1); | 1067 | if (mutex_trylock(&kexec_mutex)) { |
1078 | if (!locked) { | ||
1079 | if (kexec_crash_image) { | 1068 | if (kexec_crash_image) { |
1080 | struct pt_regs fixed_regs; | 1069 | struct pt_regs fixed_regs; |
1081 | crash_setup_regs(&fixed_regs, regs); | 1070 | crash_setup_regs(&fixed_regs, regs); |
@@ -1083,8 +1072,7 @@ void crash_kexec(struct pt_regs *regs) | |||
1083 | machine_crash_shutdown(&fixed_regs); | 1072 | machine_crash_shutdown(&fixed_regs); |
1084 | machine_kexec(kexec_crash_image); | 1073 | machine_kexec(kexec_crash_image); |
1085 | } | 1074 | } |
1086 | locked = xchg(&kexec_lock, 0); | 1075 | mutex_unlock(&kexec_mutex); |
1087 | BUG_ON(!locked); | ||
1088 | } | 1076 | } |
1089 | } | 1077 | } |
1090 | 1078 | ||
@@ -1434,7 +1422,7 @@ int kernel_kexec(void) | |||
1434 | { | 1422 | { |
1435 | int error = 0; | 1423 | int error = 0; |
1436 | 1424 | ||
1437 | if (xchg(&kexec_lock, 1)) | 1425 | if (!mutex_trylock(&kexec_mutex)) |
1438 | return -EBUSY; | 1426 | return -EBUSY; |
1439 | if (!kexec_image) { | 1427 | if (!kexec_image) { |
1440 | error = -EINVAL; | 1428 | error = -EINVAL; |
@@ -1498,8 +1486,6 @@ int kernel_kexec(void) | |||
1498 | #endif | 1486 | #endif |
1499 | 1487 | ||
1500 | Unlock: | 1488 | Unlock: |
1501 | if (!xchg(&kexec_lock, 0)) | 1489 | mutex_unlock(&kexec_mutex); |
1502 | BUG(); | ||
1503 | |||
1504 | return error; | 1490 | return error; |
1505 | } | 1491 | } |