On 08/17/16 at 09:50am, Xunlei Pang wrote: > "/sys/kernel/kexec_crash_size" only handles crashk_res, it > is fine in most cases, but sometimes we have crashk_low_res. > For example, when "crashkernel=size[KMG],high" combined with > "crashkernel=size[KMG],low" is used for 64-bit x86. > > Like crashk_res, we introduce the corresponding sysfs file > "/sys/kernel/kexec_crash_low_size" for crashk_low_res. > > So, the exact total reserved memory is the sum of the two. > > crashk_low_res can also be shrunk via this new interface, > and users should be aware of what they are doing. Cc Yinghai Lu for review since he introduced the ,high and ,low logic. > > Suggested-by: Dave Young <dyoung at redhat.com> > Signed-off-by: Xunlei Pang <xlpang at redhat.com> > --- > include/linux/kexec.h | 4 ++-- > kernel/kexec_core.c | 23 ++++++++++++----------- > kernel/ksysfs.c | 25 +++++++++++++++++++++++-- > 3 files changed, 37 insertions(+), 15 deletions(-) > > diff --git a/include/linux/kexec.h b/include/linux/kexec.h > index d743777..4f271fc 100644 > --- a/include/linux/kexec.h > +++ b/include/linux/kexec.h > @@ -304,8 +304,8 @@ int parse_crashkernel_high(char *cmdline, unsigned long long system_ram, > unsigned long long *crash_size, unsigned long long *crash_base); > int parse_crashkernel_low(char *cmdline, unsigned long long system_ram, > unsigned long long *crash_size, unsigned long long *crash_base); > -int crash_shrink_memory(unsigned long new_size); > -size_t crash_get_memory_size(void); > +int crash_shrink_memory(struct resource *res, unsigned long new_size); > +size_t crash_get_memory_size(struct resource *res); > void crash_free_reserved_phys_range(unsigned long begin, unsigned long end); > > int __weak arch_kexec_kernel_image_probe(struct kimage *image, void *buf, > diff --git a/kernel/kexec_core.c b/kernel/kexec_core.c > index 5616755..707d18e 100644 > --- a/kernel/kexec_core.c > +++ b/kernel/kexec_core.c > @@ -925,13 +925,13 @@ void crash_kexec(struct pt_regs *regs) > } > } > > -size_t crash_get_memory_size(void) > +size_t crash_get_memory_size(struct resource *res) > { > size_t size = 0; > > mutex_lock(&kexec_mutex); > - if (crashk_res.end != crashk_res.start) > - size = resource_size(&crashk_res); > + if (res->end != res->start) > + size = resource_size(res); > mutex_unlock(&kexec_mutex); > return size; > } > @@ -945,7 +945,7 @@ void __weak crash_free_reserved_phys_range(unsigned long begin, > free_reserved_page(boot_pfn_to_page(addr >> PAGE_SHIFT)); > } > > -int crash_shrink_memory(unsigned long new_size) > +int crash_shrink_memory(struct resource *res, unsigned long new_size) > { > int ret = 0; > unsigned long start, end; > @@ -958,8 +958,9 @@ int crash_shrink_memory(unsigned long new_size) > ret = -ENOENT; > goto unlock; > } > - start = crashk_res.start; > - end = crashk_res.end; > + > + start = res->start; > + end = res->end; > old_size = (end == 0) ? 0 : end - start + 1; > if (new_size >= old_size) { > ret = (new_size == old_size) ? 0 : -EINVAL; > @@ -975,17 +976,17 @@ int crash_shrink_memory(unsigned long new_size) > start = roundup(start, KEXEC_CRASH_MEM_ALIGN); > end = roundup(start + new_size, KEXEC_CRASH_MEM_ALIGN); > > - crash_free_reserved_phys_range(end, crashk_res.end); > + crash_free_reserved_phys_range(end, res->end); > > - if ((start == end) && (crashk_res.parent != NULL)) > - release_resource(&crashk_res); > + if ((start == end) && (res->parent != NULL)) > + release_resource(res); > > ram_res->start = end; > - ram_res->end = crashk_res.end; > + ram_res->end = res->end; > ram_res->flags = IORESOURCE_BUSY | IORESOURCE_SYSTEM_RAM; > ram_res->name = "System RAM"; > > - crashk_res.end = end - 1; > + res->end = end - 1; > > insert_resource(&iomem_resource, ram_res); > > diff --git a/kernel/ksysfs.c b/kernel/ksysfs.c > index ee1bc1b..3336fd5 100644 > --- a/kernel/ksysfs.c > +++ b/kernel/ksysfs.c > @@ -105,10 +105,30 @@ static ssize_t kexec_crash_loaded_show(struct kobject *kobj, > } > KERNEL_ATTR_RO(kexec_crash_loaded); > > +static ssize_t kexec_crash_low_size_show(struct kobject *kobj, > + struct kobj_attribute *attr, char *buf) > +{ > + return sprintf(buf, "%zu\n", crash_get_memory_size(&crashk_low_res)); > +} > +static ssize_t kexec_crash_low_size_store(struct kobject *kobj, > + struct kobj_attribute *attr, > + const char *buf, size_t count) > +{ > + unsigned long cnt; > + int ret; > + > + if (kstrtoul(buf, 0, &cnt)) > + return -EINVAL; > + > + ret = crash_shrink_memory(&crashk_low_res, cnt); > + return ret < 0 ? ret : count; > +} > +KERNEL_ATTR_RW(kexec_crash_low_size); > + > static ssize_t kexec_crash_size_show(struct kobject *kobj, > struct kobj_attribute *attr, char *buf) > { > - return sprintf(buf, "%zu\n", crash_get_memory_size()); > + return sprintf(buf, "%zu\n", crash_get_memory_size(&crashk_res)); > } > static ssize_t kexec_crash_size_store(struct kobject *kobj, > struct kobj_attribute *attr, > @@ -120,7 +140,7 @@ static ssize_t kexec_crash_size_store(struct kobject *kobj, > if (kstrtoul(buf, 0, &cnt)) > return -EINVAL; > > - ret = crash_shrink_memory(cnt); > + ret = crash_shrink_memory(&crashk_res, cnt); > return ret < 0 ? ret : count; > } > KERNEL_ATTR_RW(kexec_crash_size); > @@ -218,6 +238,7 @@ static struct attribute * kernel_attrs[] = { > #ifdef CONFIG_KEXEC_CORE > &kexec_loaded_attr.attr, > &kexec_crash_loaded_attr.attr, > + &kexec_crash_low_size_attr.attr, > &kexec_crash_size_attr.attr, > &vmcoreinfo_attr.attr, > #endif > -- > 1.8.3.1 >