diff options
33 files changed, 764 insertions, 577 deletions
diff --git a/Documentation/dontdiff b/Documentation/dontdiff index 354aec047c0..881e6dd03ae 100644 --- a/Documentation/dontdiff +++ b/Documentation/dontdiff @@ -141,6 +141,7 @@ mkprep mktables mktree modpost +modules.order modversions.h* offset.h offsets.h @@ -171,6 +172,7 @@ sm_tbl* split-include tags tftpboot.img +timeconst.h times.h* tkparse trix_boot.h diff --git a/Documentation/kbuild/kconfig-language.txt b/Documentation/kbuild/kconfig-language.txt index 649cb879989..00b950d1c19 100644 --- a/Documentation/kbuild/kconfig-language.txt +++ b/Documentation/kbuild/kconfig-language.txt @@ -104,14 +104,15 @@ applicable everywhere (see syntax). Reverse dependencies can only be used with boolean or tristate symbols. Note: - select is evil.... select will by brute force set a symbol - equal to 'y' without visiting the dependencies. So abusing - select you are able to select a symbol FOO even if FOO depends - on BAR that is not set. In general use select only for - non-visible symbols (no prompts anywhere) and for symbols with - no dependencies. That will limit the usefulness but on the - other hand avoid the illegal configurations all over. kconfig - should one day warn about such things. + select should be used with care. select will force + a symbol to a value without visiting the dependencies. + By abusing select you are able to select a symbol FOO even + if FOO depends on BAR that is not set. + In general use select only for non-visible symbols + (no prompts anywhere) and for symbols with no dependencies. + That will limit the usefulness but on the other hand avoid + the illegal configurations all over. + kconfig should one day warn about such things. - numerical ranges: "range" <symbol> <symbol> ["if" <expr>] This allows to limit the range of possible input values for int diff --git a/Documentation/vm/slabinfo.c b/Documentation/vm/slabinfo.c index 22d7e3e4d60..d3ce295bffa 100644 --- a/Documentation/vm/slabinfo.c +++ b/Documentation/vm/slabinfo.c @@ -31,7 +31,7 @@ struct slabinfo { int hwcache_align, object_size, objs_per_slab; int sanity_checks, slab_size, store_user, trace; int order, poison, reclaim_account, red_zone; - unsigned long partial, objects, slabs; + unsigned long partial, objects, slabs, objects_partial, objects_total; unsigned long alloc_fastpath, alloc_slowpath; unsigned long free_fastpath, free_slowpath; unsigned long free_frozen, free_add_partial, free_remove_partial; @@ -540,7 +540,8 @@ void slabcache(struct slabinfo *s) return; store_size(size_str, slab_size(s)); - snprintf(dist_str, 40, "%lu/%lu/%d", s->slabs, s->partial, s->cpu_slabs); + snprintf(dist_str, 40, "%lu/%lu/%d", s->slabs - s->cpu_slabs, + s->partial, s->cpu_slabs); if (!line++) first_line(); @@ -776,7 +777,6 @@ void totals(void) unsigned long used; unsigned long long wasted; unsigned long long objwaste; - long long objects_in_partial_slabs; unsigned long percentage_partial_slabs; unsigned long percentage_partial_objs; @@ -790,18 +790,11 @@ void totals(void) wasted = size - used; objwaste = s->slab_size - s->object_size; - objects_in_partial_slabs = s->objects - - (s->slabs - s->partial - s ->cpu_slabs) * - s->objs_per_slab; - - if (objects_in_partial_slabs < 0) - objects_in_partial_slabs = 0; - percentage_partial_slabs = s->partial * 100 / s->slabs; if (percentage_partial_slabs > 100) percentage_partial_slabs = 100; - percentage_partial_objs = objects_in_partial_slabs * 100 + percentage_partial_objs = s->objects_partial * 100 / s->objects; if (percentage_partial_objs > 100) @@ -823,8 +816,8 @@ void totals(void) min_objects = s->objects; if (used < min_used) min_used = used; - if (objects_in_partial_slabs < min_partobj) - min_partobj = objects_in_partial_slabs; + if (s->objects_partial < min_partobj) + min_partobj = s->objects_partial; if (percentage_partial_slabs < min_ppart) min_ppart = percentage_partial_slabs; if (percentage_partial_objs < min_ppartobj) @@ -848,8 +841,8 @@ void totals(void) max_objects = s->objects; if (used > max_used) max_used = used; - if (objects_in_partial_slabs > max_partobj) - max_partobj = objects_in_partial_slabs; + if (s->objects_partial > max_partobj) + max_partobj = s->objects_partial; if (percentage_partial_slabs > max_ppart) max_ppart = percentage_partial_slabs; if (percentage_partial_objs > max_ppartobj) @@ -864,7 +857,7 @@ void totals(void) total_objects += s->objects; total_used += used; - total_partobj += objects_in_partial_slabs; + total_partobj += s->objects_partial; total_ppart += percentage_partial_slabs; total_ppartobj += percentage_partial_objs; @@ -1160,6 +1153,8 @@ void read_slab_dir(void) slab->hwcache_align = get_obj("hwcache_align"); slab->object_size = get_obj("object_size"); slab->objects = get_obj("objects"); + slab->objects_partial = get_obj("objects_partial"); + slab->objects_total = get_obj("objects_total"); slab->objs_per_slab = get_obj("objs_per_slab"); slab->order = get_obj("order"); slab->partial = get_obj("partial"); @@ -1174,8 +1174,10 @@ rpm: include/config/kernel.release FORCE # Brief documentation of the typical targets used # --------------------------------------------------------------------------- -boards := $(wildcard $(srctree)/arch/$(ARCH)/configs/*_defconfig) +boards := $(wildcard $(srctree)/arch/$(SRCARCH)/configs/*_defconfig) boards := $(notdir $(boards)) +board-dirs := $(dir $(wildcard $(srctree)/arch/$(SRCARCH)/configs/*/*_defconfig)) +board-dirs := $(sort $(notdir $(board-dirs:/=))) help: @echo 'Cleaning targets:' @@ -1221,14 +1223,19 @@ help: @echo 'Documentation targets:' @$(MAKE) -f $(srctree)/Documentation/DocBook/Makefile dochelp @echo '' - @echo 'Architecture specific targets ($(ARCH)):' + @echo 'Architecture specific targets ($(SRCARCH)):' @$(if $(archhelp),$(archhelp),\ - echo ' No architecture specific help defined for $(ARCH)') + echo ' No architecture specific help defined for $(SRCARCH)') @echo '' @$(if $(boards), \ $(foreach b, $(boards), \ printf " %-24s - Build for %s\\n" $(b) $(subst _defconfig,,$(b));) \ echo '') + @$(if $(board-dirs), \ + $(foreach b, $(board-dirs), \ + printf " %-16s - Show %s-specific targets\\n" help-$(b) $(b);) \ + printf " %-16s - Show all of the above\\n" help-boards; \ + echo '') @echo ' make V=0|1 [targets] 0 => quiet build (default), 1 => verbose build' @echo ' make V=2 [targets] 2 => give reason for rebuild of target' @@ -1240,6 +1247,20 @@ help: @echo 'For further info see the ./README file' +help-board-dirs := $(addprefix help-,$(board-dirs)) + +help-boards: $(help-board-dirs) + +boards-per-dir = $(notdir $(wildcard $(srctree)/arch/$(SRCARCH)/configs/$*/*_defconfig)) + +$(help-board-dirs): help-%: + @echo 'Architecture specific targets ($(SRCARCH) $*):' + @$(if $(boards-per-dir), \ + $(foreach b, $(boards-per-dir), \ + printf " %-24s - Build for %s\\n" $*/$(b) $(subst _defconfig,,$(b));) \ + echo '') + + # Documentation targets # --------------------------------------------------------------------------- %docs: scripts_basic FORCE diff --git a/arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c b/arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c index e2d870de837..8db8f73503b 100644 --- a/arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c +++ b/arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c @@ -339,6 +339,7 @@ static unsigned int get_cur_freq_on_cpu(unsigned int cpu) { struct acpi_cpufreq_data *data = per_cpu(drv_data, cpu); unsigned int freq; + unsigned int cached_freq; dprintk("get_cur_freq_on_cpu (%d)\n", cpu); @@ -347,7 +348,16 @@ static unsigned int get_cur_freq_on_cpu(unsigned int cpu) return 0; } + cached_freq = data->freq_table[data->acpi_data->state].frequency; freq = extract_freq(get_cur_val(&cpumask_of_cpu(cpu)), data); + if (freq != cached_freq) { + /* + * The dreaded BIOS frequency change behind our back. + * Force set the frequency on next target call. + */ + data->resume = 1; + } + dprintk("cur freq = %u\n", freq); return freq; diff --git a/arch/x86/kernel/vmlinux_64.lds.S b/arch/x86/kernel/vmlinux_64.lds.S index b7ab3c335fa..fad3674b06a 100644 --- a/arch/x86/kernel/vmlinux_64.lds.S +++ b/arch/x86/kernel/vmlinux_64.lds.S @@ -209,12 +209,6 @@ SECTIONS EXIT_DATA } -/* vdso blob that is mapped into user space */ - vdso_start = . ; - .vdso : AT(ADDR(.vdso) - LOAD_OFFSET) { *(.vdso) } - . = ALIGN(PAGE_SIZE); - vdso_end = .; - #ifdef CONFIG_BLK_DEV_INITRD . = ALIGN(PAGE_SIZE); __initramfs_start = .; diff --git a/arch/x86/vdso/vdso.S b/arch/x86/vdso/vdso.S index 4b1620a1529..1d3aa6b8718 100644 --- a/arch/x86/vdso/vdso.S +++ b/arch/x86/vdso/vdso.S @@ -1,2 +1,10 @@ - .section ".vdso","a" +#include <linux/init.h> + +__INITDATA + + .globl vdso_start, vdso_end +vdso_start: .incbin "arch/x86/vdso/vdso.so" +vdso_end: + +__FINIT diff --git a/drivers/acpi/processor_thermal.c b/drivers/acpi/processor_thermal.c index 9cb43f52f7b..649ae99b921 100644 --- a/drivers/acpi/processor_thermal.c +++ b/drivers/acpi/processor_thermal.c @@ -97,7 +97,7 @@ static int acpi_processor_apply_limit(struct acpi_processor *pr) #define CPUFREQ_THERMAL_MIN_STEP 0 #define CPUFREQ_THERMAL_MAX_STEP 3 -static unsigned int cpufreq_thermal_reduction_pctg[NR_CPUS]; +static DEFINE_PER_CPU(unsigned int, cpufreq_thermal_reduction_pctg); static unsigned int acpi_thermal_cpufreq_is_init = 0; static int cpu_has_cpufreq(unsigned int cpu) @@ -113,9 +113,9 @@ static int acpi_thermal_cpufreq_increase(unsigned int cpu) if (!cpu_has_cpufreq(cpu)) return -ENODEV; - if (cpufreq_thermal_reduction_pctg[cpu] < + if (per_cpu(cpufreq_thermal_reduction_pctg, cpu) < CPUFREQ_THERMAL_MAX_STEP) { - cpufreq_thermal_reduction_pctg[cpu]++; + per_cpu(cpufreq_thermal_reduction_pctg, cpu)++; cpufreq_update_policy(cpu); return 0; } @@ -128,14 +128,14 @@ static int acpi_thermal_cpufreq_decrease(unsigned int cpu) if (!cpu_has_cpufreq(cpu)) return -ENODEV; - if (cpufreq_thermal_reduction_pctg[cpu] > + if (per_cpu(cpufreq_thermal_reduction_pctg, cpu) > (CPUFREQ_THERMAL_MIN_STEP + 1)) - cpufreq_thermal_reduction_pctg[cpu]--; + per_cpu(cpufreq_thermal_reduction_pctg, cpu)--; else - cpufreq_thermal_reduction_pctg[cpu] = 0; + per_cpu(cpufreq_thermal_reduction_pctg, cpu) = 0; cpufreq_update_policy(cpu); /* We reached max freq again and can leave passive mode */ - return !cpufreq_thermal_reduction_pctg[cpu]; + return !per_cpu(cpufreq_thermal_reduction_pctg, cpu); } static int acpi_thermal_cpufreq_notifier(struct notifier_block *nb, @@ -147,9 +147,10 @@ static int acpi_thermal_cpufreq_notifier(struct notifier_block *nb, if (event != CPUFREQ_ADJUST) goto out; - max_freq = - (policy->cpuinfo.max_freq * - (100 - cpufreq_thermal_reduction_pctg[policy->cpu] * 20)) / 100; + max_freq = ( + policy->cpuinfo.max_freq * + (100 - per_cpu(cpufreq_thermal_reduction_pctg, policy->cpu) * 20) + ) / 100; cpufreq_verify_within_limits(policy, 0, max_freq); @@ -174,7 +175,7 @@ static int cpufreq_get_cur_state(unsigned int cpu) if (!cpu_has_cpufreq(cpu)) return 0; - return cpufreq_thermal_reduction_pctg[cpu]; + return per_cpu(cpufreq_thermal_reduction_pctg, cpu); } static int cpufreq_set_cur_state(unsigned int cpu, int state) @@ -182,7 +183,7 @@ static int cpufreq_set_cur_state(unsigned int cpu, int state) if (!cpu_has_cpufreq(cpu)) return 0; - cpufreq_thermal_reduction_pctg[cpu] = state; + per_cpu(cpufreq_thermal_reduction_pctg, cpu) = state; cpufreq_update_policy(cpu); return 0; } @@ -191,8 +192,9 @@ void acpi_thermal_cpufreq_init(void) { int i; - for (i = 0; i < NR_CPUS; i++) - cpufreq_thermal_reduction_pctg[i] = 0; + for (i = 0; i < nr_cpu_ids; i++) + if (cpu_present(i)) + per_cpu(cpufreq_thermal_reduction_pctg, i) = 0; i = cpufreq_register_notifier(&acpi_thermal_cpufreq_notifier_block, CPUFREQ_POLICY_NOTIFIER); diff --git a/drivers/atm/nicstar.c b/drivers/atm/nicstar.c index 38c769f8d2b..3da804b1627 100644 --- a/drivers/atm/nicstar.c +++ b/drivers/atm/nicstar.c @@ -415,7 +415,7 @@ static int __devinit ns_init_card(int i, struct pci_dev *pcidev) card->pcidev = pcidev; membase = pci_resource_start(pcidev, 1); card->membase = ioremap(membase, NS_IOREMAP_SIZE); - if (card->membase == 0) + if (!card->membase) { printk("nicstar%d: can't ioremap() membase.\n",i); error = 3; diff --git a/drivers/char/drm/r128_cce.c b/drivers/char/drm/r128_cce.c index f36adbd3aaf..c31afbde62e 100644 --- a/drivers/char/drm/r128_cce.c +++ b/drivers/char/drm/r128_cce.c @@ -817,7 +817,7 @@ static struct drm_buf *r128_freelist_get(struct drm_device * dev) for (i = 0; i < dma->buf_count; i++) { buf = dma->buflist[i]; buf_priv = buf->dev_private; - if (buf->file_priv == 0) + if (!buf->file_priv) return buf; } diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c index 4d3c7018f0c..98b65a23099 100644 --- a/drivers/char/tty_io.c +++ b/drivers/char/tty_io.c @@ -1180,7 +1180,7 @@ struct tty_driver *tty_find_polling_driver(char *name, int *line) if (*str == ',') str++; if (*str == '\0') - str = 0; + str = NULL; if (tty_line >= 0 && tty_line <= p->num && p->poll_init && !p->poll_init(p, tty_line, str)) { diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index 35a26a3e5f6..d3575f5ec6d 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c @@ -118,9 +118,11 @@ static void handle_update(struct work_struct *work); static BLOCKING_NOTIFIER_HEAD(cpufreq_policy_notifier_list); static struct srcu_notifier_head cpufreq_transition_notifier_list; +static bool init_cpufreq_transition_notifier_list_called; static int __init init_cpufreq_transition_notifier_list(void) { srcu_init_notifier_head(&cpufreq_transition_notifier_list); + init_cpufreq_transition_notifier_list_called = true; return 0; } pure_initcall(init_cpufreq_transition_notifier_list); @@ -216,7 +218,7 @@ static void cpufreq_debug_disable_ratelimit(void) } void cpufreq_debug_printk(unsigned int type, const char *prefix, - const char *fmt, ...) + const char *fmt, ...) { char s[256]; va_list args; @@ -378,7 +380,7 @@ static struct cpufreq_governor *__find_governor(const char *str_governor) /** * cpufreq_parse_governor - parse a governor string */ -static int cpufreq_parse_governor (char *str_governor, unsigned int *policy, +static int cpufreq_parse_governor(char *str_governor, unsigned int *policy, struct cpufreq_governor **governor) { int err = -EINVAL; @@ -446,7 +448,7 @@ extern struct sysdev_class cpu_sysdev_class; #define show_one(file_name, object) \ static ssize_t show_##file_name \ -(struct cpufreq_policy * policy, char *buf) \ +(struct cpufreq_policy *policy, char *buf) \ { \ return sprintf (buf, "%u\n", policy->object); \ } @@ -465,7 +467,7 @@ static int __cpufreq_set_policy(struct cpufreq_policy *data, */ #define store_one(file_name, object) \ static ssize_t store_##file_name \ -(struct cpufreq_policy * policy, const char *buf, size_t count) \ +(struct cpufreq_policy *policy, const char *buf, size_t count) \ { \ unsigned int ret = -EINVAL; \ struct cpufreq_policy new_policy; \ @@ -490,8 +492,8 @@ store_one(scaling_max_freq,max); /** * show_cpuinfo_cur_freq - current CPU frequency as detected by hardware */ -static ssize_t show_cpuinfo_cur_freq (struct cpufreq_policy * policy, - char *buf) +static ssize_t show_cpuinfo_cur_freq(struct cpufreq_policy *policy, + char *buf) { unsigned int cur_freq = __cpufreq_get(policy->cpu); if (!cur_freq) @@ -503,8 +505,7 @@ static ssize_t show_cpuinfo_cur_freq (struct cpufreq_policy * policy, /** * show_scaling_governor - show the current policy for the specified CPU */ -static ssize_t show_scaling_governor (struct cpufreq_policy * policy, - char *buf) +static ssize_t show_scaling_governor(struct cpufreq_policy *policy, char *buf) { if(policy->policy == CPUFREQ_POLICY_POWERSAVE) return sprintf(buf, "powersave\n"); @@ -519,8 +520,8 @@ static ssize_t show_scaling_governor (struct cpufreq_policy * policy, /** * store_scaling_governor - store policy for the specified CPU */ -static ssize_t store_scaling_governor (struct cpufreq_policy * policy, - const char *buf, size_t count) +static ssize_t store_scaling_governor(struct cpufreq_policy *policy, + const char *buf, size_t count) { unsigned int ret = -EINVAL; char str_governor[16]; @@ -554,7 +555,7 @@ static ssize_t store_scaling_governor (struct cpufreq_policy * policy, /** * show_scaling_driver - show the cpufreq driver currently loaded */ -static ssize_t show_scaling_driver (struct cpufreq_policy * policy, char *buf) +static ssize_t show_scaling_driver(struct cpufreq_policy *policy, char *buf) { return scnprintf(buf, CPUFREQ_NAME_LEN, "%s\n", cpufreq_driver->name); } @@ -562,8 +563,8 @@ static ssize_t show_scaling_driver (struct cpufreq_policy * policy, char *buf) /** * show_scaling_available_governors - show the available CPUfreq governors */ -static ssize_t show_scaling_available_governors (struct cpufreq_policy *policy, - char *buf) +static ssize_t show_scaling_available_governors(struct cpufreq_policy *policy, + char *buf) { ssize_t i = 0; struct cpufreq_governor *t; @@ -585,7 +586,7 @@ out: /** * show_affected_cpus - show the CPUs affected by each transition */ -static ssize_t show_affected_cpus (struct cpufreq_policy * policy, char *buf) +static ssize_t show_affected_cpus(struct cpufreq_policy *policy, char *buf) { ssize_t i = 0; unsigned int cpu; @@ -602,7 +603,7 @@ static ssize_t show_affected_cpus (struct cpufreq_policy * policy, char *buf) } static ssize_t store_scaling_setspeed(struct cpufreq_policy *policy, - const char *buf, size_t count) + const char *buf, size_t count) { unsigned int freq = 0; unsigned int ret; @@ -651,7 +652,7 @@ define_one_rw(scaling_max_freq); define_one_rw(scaling_governor); define_one_rw(scaling_setspeed); -static struct attribute * default_attrs[] = { +static struct attribute *default_attrs[] = { &cpuinfo_min_freq.attr, &cpuinfo_max_freq.attr, &scaling_min_freq.attr, @@ -667,10 +668,10 @@ static struct attribute * default_attrs[] = { #define to_policy(k) container_of(k,struct cpufreq_policy,kobj) #define to_attr(a) container_of(a,struct freq_attr,attr) -static ssize_t show(struct kobject * kobj, struct attribute * attr ,char * buf) +static ssize_t show(struct kobject *kobj, struct attribute *attr ,char *buf) { - struct cpufreq_policy * policy = to_policy(kobj); - struct freq_attr * fattr = to_attr(attr); + struct cpufreq_policy *policy = to_policy(kobj); + struct freq_attr *fattr = to_attr(attr); ssize_t ret = -EINVAL; policy = cpufreq_cpu_get(policy->cpu); if (!policy) @@ -691,11 +692,11 @@ no_policy: return ret; } -static ssize_t store(struct kobject * kobj, struct attribute * attr, - const char * buf, size_t count) +static ssize_t store(struct kobject *kobj, struct attribute *attr, + const char *buf, size_t count) { - struct cpufreq_policy * policy = to_policy(kobj); - struct freq_attr * fattr = to_attr(attr); + struct cpufreq_policy *policy = to_policy(kobj); + struct freq_attr *fattr = to_attr(attr); ssize_t ret = -EINVAL; policy = cpufreq_cpu_get(policy->cpu); if (!policy) @@ -716,9 +717,9 @@ no_policy: return ret; } -static void cpufreq_sysfs_release(struct kobject * kobj) +static void cpufreq_sysfs_release(struct kobject *kobj) { - struct cpufreq_policy * policy = to_policy(kobj); + struct cpufreq_policy *policy = to_policy(kobj); dprintk("last reference is dropped\n"); complete(&policy->kobj_unregister); } @@ -740,7 +741,7 @@ static struct kobj_type ktype_cpufreq = { * * Adds the cpufreq interface for a CPU device. */ -static int cpufreq_add_dev (struct sys_device * sys_dev) +static int cpufreq_add_dev(struct sys_device *sys_dev) { unsigned int cpu = sys_dev->id; int ret = 0; @@ -800,7 +801,6 @@ static int cpufreq_add_dev (struct sys_device * sys_dev) ret = cpufreq_driver->init(policy); if (ret) { dprintk("initialization failed\n"); - unlock_policy_rwsem_write(cpu); goto err_out; } policy->user_policy.min = policy->cpuinfo.min_freq; @@ -823,7 +823,7 @@ static int cpufreq_add_dev (struct sys_device * sys_dev) /* check for existing affected CPUs. They may not be aware * of it due to CPU Hotplug. */ - managed_policy = cpufreq_cpu_get(j); + managed_policy = cpufreq_cpu_get(j); // FIXME: Where is this released? What about error paths? if (unlikely(managed_policy)) { /* Set proper policy_cpu */ @@ -842,14 +842,11 @@ static int cpufreq_add_dev (struct sys_device * sys_dev) ret = sysfs_create_link(&sys_dev->kobj, &managed_policy->kobj, "cpufreq"); - if (ret) { - unlock_policy_rwsem_write(cpu); + if (ret) goto err_out_driver_exit; - } cpufreq_debug_enable_ratelimit(); ret = 0; - unlock_policy_rwsem_write(cpu); goto err_out_driver_exit; /* call driver->exit() */ } } @@ -859,33 +856,26 @@ static int cpufreq_add_dev (struct sys_device * sys_dev) /* prepare interface data */ ret = kobject_init_and_add(&policy->kobj, &ktype_cpufreq, &sys_dev->kobj, "cpufreq"); - if (ret) { - unlock_policy_rwsem_write(cpu); + if (ret) goto err_out_driver_exit; - } + /* set up files for this cpu device */ drv_attr = cpufreq_driver->attr; while ((drv_attr) && (*drv_attr)) { ret = sysfs_create_file(&policy->kobj, &((*drv_attr)->attr)); - if (ret) { - unlock_policy_rwsem_write(cpu); + if (ret) goto err_out_driver_exit; - } drv_attr++; } - if (cpufreq_driver->get){ + if (cpufreq_driver->get) { ret = sysfs_create_file(&policy->kobj, &cpuinfo_cur_freq.attr); - if (ret) { - unlock_policy_rwsem_write(cpu); + if (ret) goto err_out_driver_exit; - } } - if (cpufreq_driver->target){ + if (cpufreq_driver->target) { ret = sysfs_create_file(&policy->kobj, &scaling_cur_freq.attr); - if (ret) { - unlock_policy_rwsem_write(cpu); + if (ret) goto err_out_driver_exit; - } } spin_lock_irqsave(&cpufreq_driver_lock, flags); @@ -907,10 +897,8 @@ static int cpufreq_add_dev (struct sys_device * sys_dev) cpu_sys_dev = get_cpu_sysdev(j); ret = sysfs_create_link(&cpu_sys_dev->kobj, &policy->kobj, "cpufreq"); - if (ret) { - unlock_policy_rwsem_write(cpu); + if (ret) goto err_out_unregister; - } } policy->governor = NULL; /* to assure that the starting sequence is @@ -950,6 +938,7 @@ err_out_driver_exit: cpufreq_driver->exit(policy); err_out: + unlock_policy_rwsem_write(cpu); kfree(policy); nomem_out: @@ -967,7 +956,7 @@ module_out: * Caller should already have policy_rwsem in write mode for this CPU. * This routine frees the rwsem before returning. */ -static int __cpufreq_remove_dev (struct sys_device * sys_dev) +static int __cpufreq_remove_dev(struct sys_device *sys_dev) { unsigned int cpu = sys_dev->id; unsigned long flags; @@ -1071,7 +1060,7 @@ static int __cpufreq_remove_dev (struct sys_device * sys_dev) } -static int cpufreq_remove_dev (struct sys_device * sys_dev) +static int cpufreq_remove_dev(struct sys_device *sys_dev) { unsigned int cpu = sys_dev->id; int retval; @@ -1138,7 +1127,7 @@ unsigned int cpufreq_quick_get(unsigned int cpu) cpufreq_cpu_put(policy); } - return (ret_freq); + return ret_freq; } EXPORT_SYMBOL(cpufreq_quick_get); @@ -1149,7 +1138,7 @@ static unsigned int __cpufreq_get(unsigned int cpu) unsigned int ret_freq = 0; if (!cpufreq_driver->get) - return (ret_freq); + return ret_freq; ret_freq = cpufreq_driver->get(cpu); @@ -1163,7 +1152,7 @@ static unsigned int __cpufreq_get(unsigned int cpu) } } - return (ret_freq); + return ret_freq; } /** @@ -1190,7 +1179,7 @@ unsigned int cpufreq_get(unsigned int cpu) out_policy: cpufreq_cpu_put(policy); out: - return (ret_freq); + return ret_freq; } EXPORT_SYMBOL(cpufreq_get); @@ -1199,7 +1188,7 @@ EXPORT_SYMBOL(cpufreq_get); * cpufreq_suspend - let the low level driver prepare for suspend */ -static int cpufreq_suspend(struct sys_device * sysdev, pm_message_t pmsg) +static int cpufreq_suspend(struct sys_device *sysdev, pm_message_t pmsg) { int cpu = sysdev->id; int ret = 0; @@ -1221,22 +1210,18 @@ static int cpufreq_suspend(struct sys_device * sysdev, pm_message_t pmsg) return -EINVAL; /* only handle each CPU group once */ - if (unlikely(cpu_policy->cpu != cpu)) { - cpufreq_cpu_put(cpu_policy); - return 0; - } + if (unlikely(cpu_policy->cpu != cpu)) + goto out; if (cpufreq_driver->suspend) { ret = cpufreq_driver->suspend(cpu_policy, pmsg); if (ret) { printk(KERN_ERR "cpufreq: suspend failed in ->suspend " "step on CPU %u\n", cpu_policy->cpu); - cpufreq_cpu_put(cpu_policy); - return ret; + goto out; } } - if (cpufreq_driver->flags & CPUFREQ_CONST_LOOPS) goto out; @@ -1270,7 +1255,7 @@ static int cpufreq_suspend(struct sys_device * sysdev, pm_message_t pmsg) out: cpufreq_cpu_put(cpu_policy); - return 0; + return ret; } /** @@ -1281,7 +1266,7 @@ out: * 3.) schedule call cpufreq_update_policy() ASAP as interrupts are * restored. */ -static int cpufreq_resume(struct sys_device * sysdev) +static int cpufreq_resume(struct sys_device *sysdev) { int cpu = sysdev->id; int ret = 0; @@ -1302,18 +1287,15 @@ static int cpufreq_resume(struct sys_device * sysdev) return -EINVAL; /* only handle each CPU group once */ - if (unlikely(cpu_policy->cpu != cpu)) { - cpufreq_cpu_put(cpu_policy); - return 0; - } + if (unlikely(cpu_policy->cpu != cpu)) + goto fail; if (cpufreq_driver->resume) { ret = cpufreq_driver->resume(cpu_policy); if (ret) { printk(KERN_ERR "cpufreq: resume failed in ->resume " "step on CPU %u\n", cpu_policy->cpu); - cpufreq_cpu_put(cpu_policy); - return ret; + goto fail; } } @@ -1353,6 +1335,7 @@ static int cpufreq_resume(struct sys_device * sysdev) out: schedule_work(&cpu_policy->update); +fail: cpufreq_cpu_put(cpu_policy); return ret; } @@ -1386,6 +1369,8 @@ int cpufreq_register_notifier(struct notifier_block *nb, unsigned int list) { int ret; + WARN_ON(!init_cpufreq_transition_notifier_list_called); + switch (list) { case CPUFREQ_TRANSITION_NOTIFIER: ret = srcu_notifier_chain_register( @@ -1848,7 +1833,7 @@ int cpufreq_register_driver(struct cpufreq_driver *driver_data) cpufreq_debug_enable_ratelimit(); } - return (ret); + return ret; } EXPORT_SYMBOL_GPL(cpufreq_register_driver); diff --git a/drivers/cpufreq/cpufreq_stats.c b/drivers/cpufreq/cpufreq_stats.c index 070421a5480..ef09e069433 100644 --- a/drivers/cpufreq/cpufreq_stats.c +++ b/drivers/cpufreq/cpufreq_stats.c @@ -114,7 +114,7 @@ show_trans_table(struct cpufreq_policy *policy, char *buf) stat->freq_table[i]); } if (len >= PAGE_SIZE) - return len; + return PAGE_SIZE; len += snprintf(buf + len, PAGE_SIZE - len, "\n"); @@ -131,8 +131,12 @@ show_trans_table(struct cpufreq_policy *policy, char *buf) len += snprintf(buf + len, PAGE_SIZE - len, "%9u ", stat->trans_table[i*stat->max_state+j]); } + if (len >= PAGE_SIZE) + break; len += snprintf(buf + len, PAGE_SIZE - len, "\n"); } + if (len >= PAGE_SIZE) + return PAGE_SIZE; return len; } CPUFREQ_STATDEVICE_ATTR(trans_table,0444,show_trans_table); diff --git a/include/linux/mm_types.h b/include/linux/mm_types.h index 29adaa781cb..e2bae8dde35 100644 --- a/include/linux/mm_types.h +++ b/include/linux/mm_types.h @@ -42,7 +42,10 @@ struct page { * to show when page is mapped * & limit reverse map searches. */ - unsigned int inuse; /* SLUB: Nr of objects */ + struct { /* SLUB */ + u16 inuse; + u16 objects; + }; }; union { struct { diff --git a/include/linux/slub_def.h b/include/linux/slub_def.h index 79d59c937fa..71e43a12ebb 100644 --- a/include/linux/slub_def.h +++ b/include/linux/slub_def.h @@ -29,6 +29,7 @@ enum stat_item { DEACTIVATE_TO_HEAD, /* Cpu slab was moved to the head of partials */ DEACTIVATE_TO_TAIL, /* Cpu slab was moved to the tail of partials */ DEACTIVATE_REMOTE_FREES,/* Slab contained remotely freed objects */ + ORDER_FALLBACK, /* Number of times fallback was necessary */ NR_SLUB_STAT_ITEMS }; struct kmem_cache_cpu { @@ -48,11 +49,21 @@ struct kmem_cache_node { struct list_head partial; #ifdef CONFIG_SLUB_DEBUG atomic_long_t nr_slabs; + atomic_long_t total_objects; struct list_head full; #endif }; /* + * Word size structure that can be atomically updated or read and that + * contains both the order and the number of objects that a slab of the + * given order would contain. + */ +struct kmem_cache_order_objects { + unsigned long x; +}; + +/* * Slab cache management. */ struct kmem_cache { @@ -61,7 +72,7 @@ struct kmem_cache { int size; /* The size of an object including meta data */ int objsize; /* The size of an object without meta data */ int offset; /* Free pointer offset. */ - int order; /* Current preferred allocation order */ + struct kmem_cache_order_objects oo; /* * Avoid an extra cache line for UP, SMP and for the node local to @@ -70,7 +81,8 @@ struct kmem_cache { struct kmem_cache_node local_node; /* Allocation and freeing of slabs */ - int objects; /* Number of objects in slab */ + struct kmem_cache_order_objects max; + struct kmem_cache_order_objects min; gfp_t allocflags; /* gfp flags to use on each alloc */ int refcount; /* Refcount for slab cache destroy */ void (*ctor)(struct kmem_cache *, void *); diff --git a/init/do_mounts_md.c b/init/do_mounts_md.c index 753dc54a664..7473b0c59d4 100644 --- a/init/do_mounts_md.c +++ b/init/do_mounts_md.c @@ -133,7 +133,7 @@ static void __init md_setup_drive(void) else dev = MKDEV(MD_MAJOR, minor); create_dev(name, dev); - for (i = 0; i < MD_SB_DISKS && devname != 0; i++) { + for (i = 0; i < MD_SB_DISKS && devname != NULL; i++) { char *p; char comp_name[64]; u32 rdev; diff --git a/init/do_mounts_rd.c b/init/do_mounts_rd.c index 3ac5904d1b1..46dfd64ae8f 100644 --- a/init/do_mounts_rd.c +++ b/init/do_mounts_rd.c @@ -212,7 +212,7 @@ int __init rd_load_image(char *from) } buf = kmalloc(BLOCK_SIZE, GFP_KERNEL); - if (buf == 0) { + if (!buf) { printk(KERN_ERR "RAMDISK: could not allocate buffer\n"); goto done; } diff --git a/kernel/cpuset.c b/kernel/cpuset.c index 024888bb981..48a976c52cf 100644 --- a/kernel/cpuset.c +++ b/kernel/cpuset.c @@ -1265,7 +1265,8 @@ static ssize_t cpuset_common_file_write(struct cgroup *cont, return -E2BIG; /* +1 for nul-terminator */ - if ((buffer = kmalloc(nbytes + 1, GFP_KERNEL)) == 0) + buffer = kmalloc(nbytes + 1, GFP_KERNEL); + if (!buffer) return -ENOMEM; if (copy_from_user(buffer, userbuf, nbytes)) { diff --git a/kernel/hrtimer.c b/kernel/hrtimer.c index e379ef0e9c2..dea4c9124ac 100644 --- a/kernel/hrtimer.c +++ b/kernel/hrtimer.c @@ -590,7 +590,6 @@ static inline int hrtimer_enqueue_reprogram(struct hrtimer *timer, list_add_tail(&timer->cb_entry, &base->cpu_base->cb_pending); timer->state = HRTIMER_STATE_PENDING; - raise_softirq(HRTIMER_SOFTIRQ); return 1; default: BUG(); @@ -633,6 +632,11 @@ static int hrtimer_switch_to_hres(void) return 1; } +static inline void hrtimer_raise_softirq(void) +{ + raise_softirq(HRTIMER_SOFTIRQ); +} + #else static inline int hrtimer_hres_active(void) { return 0; } @@ -651,6 +655,7 @@ static inline int hrtimer_reprogram(struct hrtimer *timer, { return 0; } +static inline void hrtimer_raise_softirq(void) { } #endif /* CONFIG_HIGH_RES_TIMERS */ @@ -850,7 +855,7 @@ hrtimer_start(struct hrtimer *timer, ktime_t tim, const enum hrtimer_mode mode) { struct hrtimer_clock_base *base, *new_base; unsigned long flags; - int ret; + int ret, raise; base = lock_hrtimer_base(timer, &flags); @@ -884,8 +889,18 @@ hrtimer_start(struct hrtimer *timer, ktime_t tim, const enum hrtimer_mode mode) enqueue_hrtimer(timer, new_base, new_base->cpu_base == &__get_cpu_var(hrtimer_bases)); + /* + * The timer may be expired and moved to the cb_pending + * list. We can not raise the softirq with base lock held due + * to a possible deadlock with runqueue lock. + */ + raise = timer->state == HRTIMER_STATE_PENDING; + unlock_hrtimer_base(timer, &flags); + if (raise) + hrtimer_raise_softirq(); + return ret; } EXPORT_SYMBOL_GPL(hrtimer_start); diff --git a/kernel/pid_namespace.c b/kernel/pid_namespace.c index 6d792b66d85..5ca37fa50be 100644 --- a/kernel/pid_namespace.c +++ b/kernel/pid_namespace.c @@ -92,7 +92,7 @@ static struct pid_namespace *create_pid_namespace(int level) atomic_set(&ns->pidmap[0].nr_free, BITS_PER_PAGE - 1); for (i = 1; i < PIDMAP_ENTRIES; i++) { - ns->pidmap[i].page = 0; + ns->pidmap[i].page = NULL; atomic_set(&ns->pidmap[i].nr_free, BITS_PER_PAGE); } diff --git a/kernel/ptrace.c b/kernel/ptrace.c index 67e392ed549..dac4b4e5729 100644 --- a/kernel/ptrace.c +++ b/kernel/ptrace.c @@ -612,7 +612,7 @@ int generic_ptrace_pokedata(struct task_struct *tsk, long addr, long data) return (copied == sizeof(data)) ? 0 : -EIO; } -#ifdef CONFIG_COMPAT +#if defined CONFIG_COMPAT && defined __ARCH_WANT_COMPAT_SYS_PTRACE #include <linux/compat.h> int compat_ptrace_request(struct task_struct *child, compat_long_t request, @@ -667,7 +667,6 @@ int compat_ptrace_request(struct task_struct *child, compat_long_t request, return ret; } -#ifdef __ARCH_WANT_COMPAT_SYS_PTRACE asmlinkage long compat_sys_ptrace(compat_long_t request, compat_long_t pid, compat_long_t addr, compat_long_t data) { @@ -710,6 +709,4 @@ asmlinkage long compat_sys_ptrace(compat_long_t request, compat_long_t pid, unlock_kernel(); return ret; } -#endif /* __ARCH_WANT_COMPAT_SYS_PTRACE */ - -#endif /* CONFIG_COMPAT */ +#endif /* CONFIG_COMPAT && __ARCH_WANT_COMPAT_SYS_PTRACE */ diff --git a/mm/hugetlb.c b/mm/hugetlb.c index df28c1773fb..2c37c67ed8c 100644 --- a/mm/hugetlb.c +++ b/mm/hugetlb.c @@ -204,7 +204,7 @@ static struct page *alloc_fresh_huge_page_node(int nid) if (page) { if (arch_prepare_hugepage(page)) { __free_pages(page, HUGETLB_PAGE_ORDER); - return 0; + return NULL; } set_compound_page_dtor(page, free_huge_page); spin_lock(&hugetlb_lock); diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c index c4ba85c8cb0..b17dca7249f 100644 --- a/mm/memory_hotplug.c +++ b/mm/memory_hotplug.c @@ -29,6 +29,8 @@ #include <asm/tlbflush.h> +#include "internal.h" + /* add this memory to iomem resource */ static struct resource *register_memory_resource(u64 start, u64 size) { diff --git a/mm/slob.c b/mm/slob.c index e2c3c0ec546..6038cbadf79 100644 --- a/mm/slob.c +++ b/mm/slob.c @@ -533,7 +533,8 @@ struct kmem_cache *kmem_cache_create(const char *name, size_t size, { struct kmem_cache *c; - c = slob_alloc(sizeof(struct kmem_cache), flags, 0, -1); + c = slob_alloc(sizeof(struct kmem_cache), + flags, ARCH_KMALLOC_MINALIGN, -1); if (c) { c->name = name; diff --git a/mm/slub.c b/mm/slub.c index 38914bc64ac..992ecd4f0d3 100644 --- a/mm/slub.c +++ b/mm/slub.c @@ -149,25 +149,6 @@ static inline void ClearSlabDebug(struct page *page) /* Enable to test recovery from slab corruption on boot */ #undef SLUB_RESILIENCY_TEST -#if PAGE_SHIFT <= 12 - -/* - * Small page size. Make sure that we do not fragment memory - */ -#define DEFAULT_MAX_ORDER 1 -#define DEFAULT_MIN_OBJECTS 4 - -#else - -/* - * Large page machines are customarily able to handle larger - * page orders. - */ -#define DEFAULT_MAX_ORDER 2 -#define DEFAULT_MIN_OBJECTS 8 - -#endif - /* * Mininum number of partial slabs. These will be left on the partial * lists even if they are empty. kmem_cache_shrink may reclaim them. @@ -204,8 +185,6 @@ static inline void ClearSlabDebug(struct page *page) /* Internal SLUB flags */ #define __OBJECT_POISON 0x80000000 /* Poison object */ #define __SYSFS_ADD_DEFERRED 0x40000000 /* Not yet visible via sysfs */ -#define __KMALLOC_CACHE 0x20000000 /* objects freed using kfree */ -#define __PAGE_ALLOC_FALLBACK 0x10000000 /* Allow fallback to page alloc */ static int kmem_size = sizeof(struct kmem_cache); @@ -296,7 +275,7 @@ static inline int check_valid_pointer(struct kmem_cache *s, return 1; base = page_address(page); - if (object < base || object >= base + s->objects * s->size || + if (object < base || object >= base + page->objects * s->size || (object - base) % s->size) { return 0; } @@ -322,8 +301,8 @@ static inline void set_freepointer(struct kmem_cache *s, void *object, void *fp) } /* Loop over all objects in a slab */ -#define for_each_object(__p, __s, __addr) \ - for (__p = (__addr); __p < (__addr) + (__s)->objects * (__s)->size;\ +#define for_each_object(__p, __s, __addr, __objects) \ + for (__p = (__addr); __p < (__addr) + (__objects) * (__s)->size;\ __p += (__s)->size) /* Scan freelist */ @@ -336,6 +315,26 @@ static inline int slab_index(void *p, struct kmem_cache *s, void *addr) return (p - addr) / s->size; } +static inline struct kmem_cache_order_objects oo_make(int order, + unsigned long size) +{ + struct kmem_cache_order_objects x = { + (order << 16) + (PAGE_SIZE << order) / size + }; + + return x; +} + +static inline int oo_order(struct kmem_cache_order_objects x) +{ + return x.x >> 16; +} + +static inline int oo_objects(struct kmem_cache_order_objects x) +{ + return x.x & ((1 << 16) - 1); +} + #ifdef CONFIG_SLUB_DEBUG /* * Debug settings: @@ -446,8 +445,8 @@ static void print_tracking(struct kmem_cache *s, void *object) static void print_page_info(struct page *page) { - printk(KERN_ERR "INFO: Slab 0x%p used=%u fp=0x%p flags=0x%04lx\n", - page, page->inuse, page->freelist, page->flags); + printk(KERN_ERR "INFO: Slab 0x%p objects=%u used=%u fp=0x%p flags=0x%04lx\n", + page, page->objects, page->inuse, page->freelist, page->flags); } @@ -647,6 +646,7 @@ static int check_pad_bytes(struct kmem_cache *s, struct page *page, u8 *p) p + off, POISON_INUSE, s->size - off); } +/* Check the pad bytes at the end of a slab page */ static int slab_pad_check(struct kmem_cache *s, struct page *page) { u8 *start; @@ -659,20 +659,20 @@ static int slab_pad_check(struct kmem_cache *s, struct page *page) return 1; start = page_address(page); - end = start + (PAGE_SIZE << s->order); - length = s->objects * s->size; - remainder = end - (start + length); + length = (PAGE_SIZE << compound_order(page)); + end = start + length; + remainder = length % s->size; if (!remainder) return 1; - fault = check_bytes(start + length, POISON_INUSE, remainder); + fault = check_bytes(end - remainder, POISON_INUSE, remainder); if (!fault) return 1; while (end > fault && end[-1] == POISON_INUSE) end--; slab_err(s, page, "Padding overwritten. 0x%p-0x%p", fault, end - 1); - print_section("Padding", start, length); + print_section("Padding", end - remainder, remainder); restore_bytes(s, "slab padding", POISON_INUSE, start, end); return 0; @@ -734,15 +734,24 @@ static int check_object(struct kmem_cache *s, struct page *page, static int check_slab(struct kmem_cache *s, struct page *page) { + int maxobj; + VM_BUG_ON(!irqs_disabled()); if (!PageSlab(page)) { slab_err(s, page, "Not a valid slab page"); return 0; } - if (page->inuse > s->objects) { + + maxobj = (PAGE_SIZE << compound_order(page)) / s->size; + if (page->objects > maxobj) { + slab_err(s, page, "objects %u > max %u", + s->name, page->objects, maxobj); + return 0; + } + if (page->inuse > page->objects) { slab_err(s, page, "inuse %u > max %u", - s->name, page->inuse, s->objects); + s->name, page->inuse, page->objects); return 0; } /* Slab_pad_check fixes things up after itself */ @@ -759,8 +768,9 @@ static int on_freelist(struct kmem_cache *s, struct page *page, void *search) int nr = 0; void *fp = page->freelist; void *object = NULL; + unsigned long max_objects; - while (fp && nr <= s->objects) { + while (fp && nr <= page->objects) { if (fp == search) return 1; if (!check_valid_pointer(s, page, fp)) { @@ -772,7 +782,7 @@ static int on_freelist(struct kmem_cache *s, struct page *page, void *search) } else { slab_err(s, page, "Freepointer corrupt"); page->freelist = NULL; - page->inuse = s->objects; + page->inuse = page->objects; slab_fix(s, "Freelist cleared"); return 0; } @@ -783,10 +793,20 @@ static int on_freelist(struct kmem_cache *s, struct page *page, void *search) nr++; } - if (page->inuse != s->objects - nr) { + max_objects = (PAGE_SIZE << compound_order(page)) / s->size; + if (max_objects > 65535) + max_objects = 65535; + + if (page->objects != max_objects) { + slab_err(s, page, "Wrong number of objects. Found %d but " + "should be %d", page->objects, max_objects); + page->objects = max_objects; + slab_fix(s, "Number of objects adjusted."); + } + if (page->inuse != page->objects - nr) { slab_err(s, page, "Wrong object count. Counter is %d but " - "counted were %d", page->inuse, s->objects - nr); - page->inuse = s->objects - nr; + "counted were %d", page->inuse, page->objects - nr); + page->inuse = page->objects - nr; slab_fix(s, "Object count adjusted."); } return search == NULL; @@ -840,7 +860,7 @@ static inline unsigned long slabs_node(struct kmem_cache *s, int node) return atomic_long_read(&n->nr_slabs); } -static inline void inc_slabs_node(struct kmem_cache *s, int node) +static inline void inc_slabs_node(struct kmem_cache *s, int node, int objects) { struct kmem_cache_node *n = get_node(s, node); @@ -850,14 +870,17 @@ static inline void inc_slabs_node(struct kmem_cache *s, int node) * dilemma by deferring the increment of the count during * bootstrap (see early_kmem_cache_node_alloc). */ - if (!NUMA_BUILD || n) + if (!NUMA_BUILD || n) { atomic_long_inc(&n->nr_slabs); + atomic_long_add(objects, &n->total_objects); + } } -static inline void dec_slabs_node(struct kmem_cache *s, int node) +static inline void dec_slabs_node(struct kmem_cache *s, int node, int objects) { struct kmem_cache_node *n = get_node(s, node); atomic_long_dec(&n->nr_slabs); + atomic_long_sub(objects, &n->total_objects); } /* Object debug checks for alloc/free paths */ @@ -905,7 +928,7 @@ bad: * as used avoids touching the remaining objects. */ slab_fix(s, "Marking all objects used"); - page->inuse = s->objects; + page->inuse = page->objects; page->freelist = NULL; } return 0; @@ -1055,31 +1078,52 @@ static inline unsigned long kmem_cache_flags(unsigned long objsize, static inline unsigned long slabs_node(struct kmem_cache *s, int node) { return 0; } -static inline void inc_slabs_node(struct kmem_cache *s, int node) {} -static inline void dec_slabs_node(struct kmem_cache *s, int node) {} +static inline void inc_slabs_node(struct kmem_cache *s, int node, + int objects) {} +static inline void dec_slabs_node(struct kmem_cache *s, int node, + int objects) {} #endif + /* * Slab allocation and freeing */ +static inline struct page *alloc_slab_page(gfp_t flags, int node, + struct kmem_cache_order_objects oo) +{ + int order = oo_order(oo); + + if (node == -1) + return alloc_pages(flags, order); + else + return alloc_pages_node(node, flags, order); +} + static struct page *allocate_slab(struct kmem_cache *s, gfp_t flags, int node) { struct page *page; - int pages = 1 << s->order; + struct kmem_cache_order_objects oo = s->oo; flags |= s->allocflags; - if (node == -1) - page = alloc_pages(flags, s->order); - else - page = alloc_pages_node(node, flags, s->order); - - if (!page) - return NULL; + page = alloc_slab_page(flags | __GFP_NOWARN | __GFP_NORETRY, node, + oo); + if (unlikely(!page)) { + oo = s->min; + /* + * Allocation may have failed due to fragmentation. + * Try a lower order alloc if possible + */ + page = alloc_slab_page(flags, node, oo); + if (!page) + return NULL; + stat(get_cpu_slab(s, raw_smp_processor_id()), ORDER_FALLBACK); + } + page->objects = oo_objects(oo); mod_zone_page_state(page_zone(page), (s->flags & SLAB_RECLAIM_ACCOUNT) ? NR_SLAB_RECLAIMABLE : NR_SLAB_UNRECLAIMABLE, - pages); + 1 << oo_order(oo)); return page; } @@ -1106,7 +1150,7 @@ static struct page *new_slab(struct kmem_cache *s, gfp_t flags, int node) if (!page) goto out; - inc_slabs_node(s, page_to_nid(page)); + inc_slabs_node(s, page_to_nid(page), page->objects); page->slab = s; page->flags |= 1 << PG_slab; if (s->flags & (SLAB_DEBUG_FREE | SLAB_RED_ZONE | SLAB_POISON | @@ -1116,10 +1160,10 @@ static struct page *new_slab(struct kmem_cache *s, gfp_t flags, int node) start = page_address(page); if (unlikely(s->flags & SLAB_POISON)) - memset(start, POISON_INUSE, PAGE_SIZE << s->order); + memset(start, POISON_INUSE, PAGE_SIZE << compound_order(page)); last = start; - for_each_object(p, s, start) { + for_each_object(p, s, start, page->objects) { setup_object(s, page, last); set_freepointer(s, last, p); last = p; @@ -1135,13 +1179,15 @@ out: static void __free_slab(struct kmem_cache *s, struct page *page) { - int pages = 1 << s->order; + int order = compound_order(page); + int pages = 1 << order; if (unlikely(SlabDebug(page))) { void *p; slab_pad_check(s, page); - for_each_object(p, s, page_address(page)) + for_each_object(p, s, page_address(page), + page->objects) check_object(s, page, p, 0); ClearSlabDebug(page); } @@ -1153,7 +1199,7 @@ static void __free_slab(struct kmem_cache *s, struct page *page) __ClearPageSlab(page); reset_page_mapcount(page); - __free_pages(page, s->order); + __free_pages(page, order); } static void rcu_free_slab(struct rcu_head *h) @@ -1179,7 +1225,7 @@ static void free_slab(struct kmem_cache *s, struct page *page) static void discard_slab(struct kmem_cache *s, struct page *page) { - dec_slabs_node(s, page_to_nid(page)); + dec_slabs_node(s, page_to_nid(page), page->objects); free_slab(s, page); } @@ -1515,7 +1561,7 @@ load_freelist: goto debug; c->freelist = object[c->offset]; - c->page->inuse = s->objects; + c->page->inuse = c->page->objects; c->page->freelist = NULL; c->node = page_to_nid(c->page); unlock_out: @@ -1552,27 +1598,6 @@ new_slab: c->page = new; goto load_freelist; } - - /* - * No memory available. - * - * If the slab uses higher order allocs but the object is - * smaller than a page size then we can fallback in emergencies - * to the page allocator via kmalloc_large. The page allocator may - * have failed to obtain a higher order page and we can try to - * allocate a single page if the object fits into a single page. - * That is only possible if certain conditions are met that are being - * checked when a slab is created. - */ - if (!(gfpflags & __GFP_NORETRY) && - (s->flags & __PAGE_ALLOC_FALLBACK)) { - if (gfpflags & __GFP_WAIT) - local_irq_enable(); - object = kmalloc_large(s->objsize, gfpflags); - if (gfpflags & __GFP_WAIT) - local_irq_disable(); - return object; - } return NULL; debug: if (!alloc_debug_processing(s, c->page, object, addr)) @@ -1773,8 +1798,8 @@ static struct page *get_object_page(const void *x) * take the list_lock. */ static int slub_min_order; -static int slub_max_order = DEFAULT_MAX_ORDER; -static int slub_min_objects = DEFAULT_MIN_OBJECTS; +static int slub_max_order = PAGE_ALLOC_COSTLY_ORDER; +static int slub_min_objects; /* * Merge control. If this is set then no merging of slab caches will occur. @@ -1789,7 +1814,7 @@ static int slub_nomerge; * system components. Generally order 0 allocations should be preferred since * order 0 does not cause fragmentation in the page allocator. Larger objects * be problematic to put into order 0 slabs because there may be too much - * unused space left. We go to a higher order if more than 1/8th of the slab + * unused space left. We go to a higher order if more than 1/16th of the slab * would be wasted. * * In order to reach satisfactory performance we must ensure that a minimum @@ -1814,6 +1839,9 @@ static inline int slab_order(int size, int min_objects, int rem; int min_order = slub_min_order; + if ((PAGE_SIZE << min_order) / size > 65535) + return get_order(size * 65535) - 1; + for (order = max(min_order, fls(min_objects * size - 1) - PAGE_SHIFT); order <= max_order; order++) { @@ -1848,8 +1876,10 @@ static inline int calculate_order(int size) * we reduce the minimum objects required in a slab. */ min_objects = slub_min_objects; + if (!min_objects) + min_objects = 4 * (fls(nr_cpu_ids) + 1); while (min_objects > 1) { - fraction = 8; + fraction = 16; while (fraction >= 4) { order = slab_order(size, min_objects, slub_max_order, fraction); @@ -2091,7 +2121,7 @@ static struct kmem_cache_node *early_kmem_cache_node_alloc(gfp_t gfpflags, init_tracking(kmalloc_caches, n); #endif init_kmem_cache_node(n); - inc_slabs_node(kmalloc_caches, node); + inc_slabs_node(kmalloc_caches, node, page->objects); /* * lockdep requires consistent irq usage for each lock @@ -2167,11 +2197,12 @@ static int init_kmem_cache_nodes(struct kmem_cache *s, gfp_t gfpflags) * calculate_sizes() determines the order and the distribution of data within * a slab object. */ -static int calculate_sizes(struct kmem_cache *s) +static int calculate_sizes(struct kmem_cache *s, int forced_order) { unsigned long flags = s->flags; unsigned long size = s->objsize; unsigned long align = s->align; + int order; /* * Round up object size to the next word boundary. We can only @@ -2255,26 +2286,16 @@ static int calculate_sizes(struct kmem_cache *s) */ size = ALIGN(size, align); s->size = size; + if (forced_order >= 0) + order = forced_order; + else + order = calculate_order(size); - if ((flags & __KMALLOC_CACHE) && - PAGE_SIZE / size < slub_min_objects) { - /* - * Kmalloc cache that would not have enough objects in - * an order 0 page. Kmalloc slabs can fallback to - * page allocator order 0 allocs so take a reasonably large - * order that will allows us a good number of objects. - */ - s->order = max(slub_max_order, PAGE_ALLOC_COSTLY_ORDER); - s->flags |= __PAGE_ALLOC_FALLBACK; - s->allocflags |= __GFP_NOWARN; - } else - s->order = calculate_order(size); - - if (s->order < 0) + if (order < 0) return 0; s->allocflags = 0; - if (s->order) + if (order) s->allocflags |= __GFP_COMP; if (s->flags & SLAB_CACHE_DMA) @@ -2286,9 +2307,12 @@ static int calculate_sizes(struct kmem_cache *s) /* * Determine the number of objects per slab */ - s->objects = (PAGE_SIZE << s->order) / size; + s->oo = oo_make(order, size); + s->min = oo_make(get_order(size), size); + if (oo_objects(s->oo) > oo_objects(s->max)) + s->max = s->oo; - return !!s->objects; + return !!oo_objects(s->oo); } @@ -2304,7 +2328,7 @@ static int kmem_cache_open(struct kmem_cache *s, gfp_t gfpflags, s->align = align; s->flags = kmem_cache_flags(size, flags, name, ctor); - if (!calculate_sizes(s)) + if (!calculate_sizes(s, -1)) goto error; s->refcount = 1; @@ -2321,7 +2345,7 @@ error: if (flags & SLAB_PANIC) panic("Cannot create slab %s size=%lu realsize=%u " "order=%u offset=%u flags=%lx\n", - s->name, (unsigned long)size, s->size, s->order, + s->name, (unsigned long)size, s->size, oo_order(s->oo), s->offset, flags); return 0; } @@ -2367,26 +2391,52 @@ const char *kmem_cache_name(struct kmem_cache *s) } EXPORT_SYMBOL(kmem_cache_name); +static void list_slab_objects(struct kmem_cache *s, struct page *page, + const char *text) +{ +#ifdef CONFIG_SLUB_DEBUG + void *addr = page_address(page); + void *p; + DECLARE_BITMAP(map, page->objects); + + bitmap_zero(map, page->objects); + slab_err(s, page, "%s", text); + slab_lock(page); + for_each_free_object(p, s, page->freelist) + set_bit(slab_index(p, s, addr), map); + + for_each_object(p, s, addr, page->objects) { + + if (!test_bit(slab_index(p, s, addr), map)) { + printk(KERN_ERR "INFO: Object 0x%p @offset=%tu\n", + p, p - addr); + print_tracking(s, p); + } + } + slab_unlock(page); +#endif +} + /* - * Attempt to free all slabs on a node. Return the number of slabs we - * were unable to free. + * Attempt to free all partial slabs on a node. */ -static int free_list(struct kmem_cache *s, struct kmem_cache_node *n, - struct list_head *list) +static void free_partial(struct kmem_cache *s, struct kmem_cache_node *n) { - int slabs_inuse = 0; unsigned long flags; struct page *page, *h; spin_lock_irqsave(&n->list_lock, flags); - list_for_each_entry_safe(page, h, list, lru) + list_for_each_entry_safe(page, h, &n->partial, lru) { if (!page->inuse) { list_del(&page->lru); discard_slab(s, page); - } else - slabs_inuse++; + n->nr_partial--; + } else { + list_slab_objects(s, page, + "Objects remaining on kmem_cache_close()"); + } + } spin_unlock_irqrestore(&n->list_lock, flags); - return slabs_inuse; } /* @@ -2403,8 +2453,8 @@ static inline int kmem_cache_close(struct kmem_cache *s) for_each_node_state(node, N_NORMAL_MEMORY) { struct kmem_cache_node *n = get_node(s, node); - n->nr_partial -= free_list(s, n, &n->partial); - if (slabs_node(s, node)) + free_partial(s, n); + if (n->nr_partial || slabs_node(s, node)) return 1; } free_kmem_cache_nodes(s); @@ -2422,8 +2472,11 @@ void kmem_cache_destroy(struct kmem_cache *s) if (!s->refcount) { list_del(&s->list); up_write(&slub_lock); - if (kmem_cache_close(s)) - WARN_ON(1); + if (kmem_cache_close(s)) { + printk(KERN_ERR "SLUB %s: %s called for cache that " + "still has objects.\n", s->name, __func__); + dump_stack(); + } sysfs_slab_remove(s); } else up_write(&slub_lock); @@ -2482,7 +2535,7 @@ static struct kmem_cache *create_kmalloc_cache(struct kmem_cache *s, down_write(&slub_lock); if (!kmem_cache_open(s, gfp_flags, name, size, ARCH_KMALLOC_MINALIGN, - flags | __KMALLOC_CACHE, NULL)) + flags, NULL)) goto panic; list_add(&s->list, &slab_caches); @@ -2730,8 +2783,9 @@ int kmem_cache_shrink(struct kmem_cache *s) struct kmem_cache_node *n; struct page *page; struct page *t; + int objects = oo_objects(s->max); struct list_head *slabs_by_inuse = - kmalloc(sizeof(struct list_head) * s->objects, GFP_KERNEL); + kmalloc(sizeof(struct list_head) * objects, GFP_KERNEL); unsigned long flags; if (!slabs_by_inuse) @@ -2744,7 +2798,7 @@ int kmem_cache_shrink(struct kmem_cache *s) if (!n->nr_partial) continue; - for (i = 0; i < s->objects; i++) + for (i = 0; i < objects; i++) INIT_LIST_HEAD(slabs_by_inuse + i); spin_lock_irqsave(&n->list_lock, flags); @@ -2776,7 +2830,7 @@ int kmem_cache_shrink(struct kmem_cache *s) * Rebuild the partial list with the slabs filled up most * first and the least used slabs at the end. */ - for (i = s->objects - 1; i >= 0; i--) + for (i = objects - 1; i >= 0; i--) list_splice(slabs_by_inuse + i, n->partial.prev); spin_unlock_irqrestore(&n->list_lock, flags); @@ -2997,9 +3051,6 @@ static int slab_unmergeable(struct kmem_cache *s) if (slub_nomerge || (s->flags & SLUB_NEVER_MERGE)) return 1; - if ((s->flags & __PAGE_ALLOC_FALLBACK)) - return 1; - if (s->ctor) return 1; @@ -3192,7 +3243,8 @@ void *__kmalloc_node_track_caller(size_t size, gfp_t gfpflags, } #if (defined(CONFIG_SYSFS) && defined(CONFIG_SLUB_DEBUG)) || defined(CONFIG_SLABINFO) -static unsigned long count_partial(struct kmem_cache_node *n) +static unsigned long count_partial(struct kmem_cache_node *n, + int (*get_count)(struct page *)) { unsigned long flags; unsigned long x = 0; @@ -3200,10 +3252,25 @@ static unsigned long count_partial(struct kmem_cache_node *n) spin_lock_irqsave(&n->list_lock, flags); list_for_each_entry(page, &n->partial, lru) - x += page->inuse; + x += get_count(page); spin_unlock_irqrestore(&n->list_lock, flags); return x; } + +static int count_inuse(struct page *page) +{ + return page->inuse; +} + +static int count_total(struct page *page) +{ + return page->objects; +} + +static int count_free(struct page *page) +{ + return page->objects - page->inuse; +} #endif #if defined(CONFIG_SYSFS) && defined(CONFIG_SLUB_DEBUG) @@ -3218,7 +3285,7 @@ static int validate_slab(struct kmem_cache *s, struct page *page, return 0; /* Now we know that a valid freelist exists */ - bitmap_zero(map, s->objects); + bitmap_zero(map, page->objects); for_each_free_object(p, s, page->freelist) { set_bit(slab_index(p, s, addr), map); @@ -3226,7 +3293,7 @@ static int validate_slab(struct kmem_cache *s, struct page *page, return 0; } - for_each_object(p, s, addr) + for_each_object(p, s, addr, page->objects) if (!test_bit(slab_index(p, s, addr), map)) if (!check_object(s, page, p, 1)) return 0; @@ -3292,7 +3359,7 @@ static long validate_slab_cache(struct kmem_cache *s) { int node; unsigned long count = 0; - unsigned long *map = kmalloc(BITS_TO_LONGS(s->objects) * + unsigned long *map = kmalloc(BITS_TO_LONGS(oo_objects(s->max)) * sizeof(unsigned long), GFP_KERNEL); if (!map) @@ -3495,14 +3562,14 @@ static void process_slab(struct loc_track *t, struct kmem_cache *s, struct page *page, enum track_item alloc) { void *addr = page_address(page); - DECLARE_BITMAP(map, s->objects); + DECLARE_BITMAP(map, page->objects); void *p; - bitmap_zero(map, s->objects); + bitmap_zero(map, page->objects); for_each_free_object(p, s, page->freelist) set_bit(slab_index(p, s, addr), map); - for_each_object(p, s, addr) + for_each_object(p, s, addr, page->objects) if (!test_bit(slab_index(p, s, addr), map)) add_location(t, s, get_track(s, p, alloc)); } @@ -3592,22 +3659,23 @@ static int list_locations(struct kmem_cache *s, char *buf, } enum slab_stat_type { - SL_FULL, - SL_PARTIAL, - SL_CPU, - SL_OBJECTS + SL_ALL, /* All slabs */ + SL_PARTIAL, /* Only partially allocated slabs */ + SL_CPU, /* Only slabs used for cpu caches */ + SL_OBJECTS, /* Determine allocated objects not slabs */ + SL_TOTAL /* Determine object capacity not slabs */ }; -#define SO_FULL (1 << SL_FULL) +#define SO_ALL (1 << SL_ALL) #define SO_PARTIAL (1 << SL_PARTIAL) #define SO_CPU (1 << SL_CPU) #define SO_OBJECTS (1 << SL_OBJECTS) +#define SO_TOTAL (1 << SL_TOTAL) static ssize_t show_slab_objects(struct kmem_cache *s, char *buf, unsigned long flags) { unsigned long total = 0; - int cpu; int node; int x; unsigned long *nodes; @@ -3618,56 +3686,60 @@ static ssize_t show_slab_objects(struct kmem_cache *s, return -ENOMEM; per_cpu = nodes + nr_node_ids; - for_each_possible_cpu(cpu) { - struct page *page; - struct kmem_cache_cpu *c = get_cpu_slab(s, cpu); + if (flags & SO_CPU) { + int cpu; - if (!c) - continue; + for_each_possible_cpu(cpu) { + struct kmem_cache_cpu *c = get_cpu_slab(s, cpu); - page = c->page; - node = c->node; - if (node < 0) - continue; - if (page) { - if (flags & SO_CPU) { - if (flags & SO_OBJECTS) - x = page->inuse; + if (!c || c->node < 0) + continue; + + if (c->page) { + if (flags & SO_TOTAL) + x = c->page->objects; + else if (flags & SO_OBJECTS) + x = c->page->inuse; else x = 1; + total += x; - nodes[node] += x; + nodes[c->node] += x; } - per_cpu[node]++; + per_cpu[c->node]++; } } - for_each_node_state(node, N_NORMAL_MEMORY) { - struct kmem_cache_node *n = get_node(s, node); + if (flags & SO_ALL) { + for_each_node_state(node, N_NORMAL_MEMORY) { + struct kmem_cache_node *n = get_node(s, node); + + if (flags & SO_TOTAL) + x = atomic_long_read(&n->total_objects); + else if (flags & SO_OBJECTS) + x = atomic_long_read(&n->total_objects) - + count_partial(n, count_free); - if (flags & SO_PARTIAL) { - if (flags & SO_OBJECTS) - x = count_partial(n); else - x = n->nr_partial; + x = atomic_long_read(&n->nr_slabs); total += x; nodes[node] += x; } - if (flags & SO_FULL) { - int full_slabs = atomic_long_read(&n->nr_slabs) - - per_cpu[node] - - n->nr_partial; + } else if (flags & SO_PARTIAL) { + for_each_node_state(node, N_NORMAL_MEMORY) { + struct kmem_cache_node *n = get_node(s, node); - if (flags & SO_OBJECTS) - x = full_slabs * s->objects; + if (flags & SO_TOTAL) + x = count_partial(n, count_total); + else if (flags & SO_OBJECTS) + x = count_partial(n, count_inuse); else - x = full_slabs; + x = n->nr_partial; total += x; nodes[node] += x; } } - x = sprintf(buf, "%lu", total); #ifdef CONFIG_NUMA for_each_node_state(node, N_NORMAL_MEMORY) @@ -3682,14 +3754,6 @@ static ssize_t show_slab_objects(struct kmem_cache *s, static int any_slab_objects(struct kmem_cache *s) { int node; - int cpu; - - for_each_possible_cpu(cpu) { - struct kmem_cache_cpu *c = get_cpu_slab(s, cpu); - - if (c && c->page) - return 1; - } for_each_online_node(node) { struct kmem_cache_node *n = get_node(s, node); @@ -3697,7 +3761,7 @@ static int any_slab_objects(struct kmem_cache *s) if (!n) continue; - if (n->nr_partial || atomic_long_read(&n->nr_slabs)) + if (atomic_read(&n->total_objects)) return 1; } return 0; @@ -3739,15 +3803,27 @@ SLAB_ATTR_RO(object_size); static ssize_t objs_per_slab_show(struct kmem_cache *s, char *buf) { - return sprintf(buf, "%d\n", s->objects); + return sprintf(buf, "%d\n", oo_objects(s->oo)); } SLAB_ATTR_RO(objs_per_slab); +static ssize_t order_store(struct kmem_cache *s, + const char *buf, size_t length) +{ + int order = simple_strtoul(buf, NULL, 10); + + if (order > slub_max_order || order < slub_min_order) + return -EINVAL; + + calculate_sizes(s, order); + return length; +} + static ssize_t order_show(struct kmem_cache *s, char *buf) { - return sprintf(buf, "%d\n", s->order); + return sprintf(buf, "%d\n", oo_order(s->oo)); } -SLAB_ATTR_RO(order); +SLAB_ATTR(order); static ssize_t ctor_show(struct kmem_cache *s, char *buf) { @@ -3768,7 +3844,7 @@ SLAB_ATTR_RO(aliases); static ssize_t slabs_show(struct kmem_cache *s, char *buf) { - return show_slab_objects(s, buf, SO_FULL|SO_PARTIAL|SO_CPU); + return show_slab_objects(s, buf, SO_ALL); } SLAB_ATTR_RO(slabs); @@ -3786,10 +3862,22 @@ SLAB_ATTR_RO(cpu_slabs); static ssize_t objects_show(struct kmem_cache *s, char *buf) { - return show_slab_objects(s, buf, SO_FULL|SO_PARTIAL|SO_CPU|SO_OBJECTS); + return show_slab_objects(s, buf, SO_ALL|SO_OBJECTS); } SLAB_ATTR_RO(objects); +static ssize_t objects_partial_show(struct kmem_cache *s, char *buf) +{ + return show_slab_objects(s, buf, SO_PARTIAL|SO_OBJECTS); +} +SLAB_ATTR_RO(objects_partial); + +static ssize_t total_objects_show(struct kmem_cache *s, char *buf) +{ + return show_slab_objects(s, buf, SO_ALL|SO_TOTAL); +} +SLAB_ATTR_RO(total_objects); + static ssize_t sanity_checks_show(struct kmem_cache *s, char *buf) { return sprintf(buf, "%d\n", !!(s->flags & SLAB_DEBUG_FREE)); @@ -3869,7 +3957,7 @@ static ssize_t red_zone_store(struct kmem_cache *s, s->flags &= ~SLAB_RED_ZONE; if (buf[0] == '1') s->flags |= SLAB_RED_ZONE; - calculate_sizes(s); + calculate_sizes(s, -1); return length; } SLAB_ATTR(red_zone); @@ -3888,7 +3976,7 @@ static ssize_t poison_store(struct kmem_cache *s, s->flags &= ~SLAB_POISON; if (buf[0] == '1') s->flags |= SLAB_POISON; - calculate_sizes(s); + calculate_sizes(s, -1); return length; } SLAB_ATTR(poison); @@ -3907,7 +3995,7 @@ static ssize_t store_user_store(struct kmem_cache *s, s->flags &= ~SLAB_STORE_USER; if (buf[0] == '1') s->flags |= SLAB_STORE_USER; - calculate_sizes(s); + calculate_sizes(s, -1); return length; } SLAB_ATTR(store_user); @@ -4038,7 +4126,7 @@ STAT_ATTR(DEACTIVATE_EMPTY, deactivate_empty); STAT_ATTR(DEACTIVATE_TO_HEAD, deactivate_to_head); STAT_ATTR(DEACTIVATE_TO_TAIL, deactivate_to_tail); STAT_ATTR(DEACTIVATE_REMOTE_FREES, deactivate_remote_frees); - +STAT_ATTR(ORDER_FALLBACK, order_fallback); #endif static struct attribute *slab_attrs[] = { @@ -4047,6 +4135,8 @@ static struct attribute *slab_attrs[] = { &objs_per_slab_attr.attr, &order_attr.attr, &objects_attr.attr, + &objects_partial_attr.attr, + &total_objects_attr.attr, &slabs_attr.attr, &partial_attr.attr, &cpu_slabs_attr.attr, @@ -4089,6 +4179,7 @@ static struct attribute *slab_attrs[] = { &deactivate_to_head_attr.attr, &deactivate_to_tail_attr.attr, &deactivate_remote_frees_attr.attr, + &order_fallback_attr.attr, #endif NULL }; @@ -4375,7 +4466,8 @@ static int s_show(struct seq_file *m, void *p) unsigned long nr_partials = 0; unsigned long nr_slabs = 0; unsigned long nr_inuse = 0; - unsigned long nr_objs; + unsigned long nr_objs = 0; + unsigned long nr_free = 0; struct kmem_cache *s; int node; @@ -4389,14 +4481,15 @@ static int s_show(struct seq_file *m, void *p) nr_partials += n->nr_partial; nr_slabs += atomic_long_read(&n->nr_slabs); - nr_inuse += count_partial(n); + nr_objs += atomic_long_read(&n->total_objects); + nr_free += count_partial(n, count_free); } - nr_objs = nr_slabs * s->objects; - nr_inuse += (nr_slabs - nr_partials) * s->objects; + nr_inuse = nr_objs - nr_free; seq_printf(m, "%-17s %6lu %6lu %6u %4u %4d", s->name, nr_inuse, - nr_objs, s->size, s->objects, (1 << s->order)); + nr_objs, s->size, oo_objects(s->oo), + (1 << oo_order(s->oo))); seq_printf(m, " : tunables %4u %4u %4u", 0, 0, 0); seq_printf(m, " : slabdata %6lu %6lu %6lu", nr_slabs, nr_slabs, 0UL); diff --git a/scripts/gen_initramfs_list.sh b/scripts/gen_initramfs_list.sh index 684fb9cdc05..5f3415f2873 100644 --- a/scripts/gen_initramfs_list.sh +++ b/scripts/gen_initramfs_list.sh @@ -135,7 +135,7 @@ parse() { str="${ftype} ${name} ${str} ${dev} ${maj} ${min}" ;; "slink") - local target=`field 11 $(LC_ALL=C ls -l "${location}")` + local target=`readlink "${location}"` str="${ftype} ${name} ${target} ${str}" ;; *) diff --git a/scripts/kconfig/lex.zconf.c_shipped b/scripts/kconfig/lex.zconf.c_shipped index bed0f4e2d2f..6a61cee4a32 100644 --- a/scripts/kconfig/lex.zconf.c_shipped +++ b/scripts/kconfig/lex.zconf.c_shipped @@ -5,25 +5,6 @@ /* A lexical scanner generated by flex */ -#define yy_create_buffer zconf_create_buffer -#define yy_delete_buffer zconf_delete_buffer -#define yy_flex_debug zconf_flex_debug -#define yy_init_buffer zconf_init_buffer -#define yy_flush_buffer zconf_flush_buffer -#define yy_load_buffer_state zconf_load_buffer_state -#define yy_switch_to_buffer zconf_switch_to_buffer -#define yyin zconfin -#define yyleng zconfleng -#define yylex zconflex -#define yylineno zconflineno -#define yyout zconfout -#define yyrestart zconfrestart -#define yytext zconftext -#define yywrap zconfwrap -#define yyalloc zconfalloc -#define yyrealloc zconfrealloc -#define yyfree zconffree - #define FLEX_SCANNER #define YY_FLEX_MAJOR_VERSION 2 #define YY_FLEX_MINOR_VERSION 5 @@ -354,7 +335,7 @@ void zconffree (void * ); /* Begin user sect3 */ -#define zconfwrap(n) 1 +#define zconfwrap() 1 #define YY_SKIP_YYWRAP typedef unsigned char YY_CHAR; @@ -1535,7 +1516,7 @@ static int yy_get_next_buffer (void) /* Read in more data. */ YY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]), - (yy_n_chars), num_to_read ); + (yy_n_chars), (size_t) num_to_read ); YY_CURRENT_BUFFER_LVALUE->yy_n_chars = (yy_n_chars); } @@ -2007,7 +1988,7 @@ YY_BUFFER_STATE zconf_scan_buffer (char * base, yy_size_t size ) /** Setup the input buffer state to scan a string. The next call to zconflex() will * scan from a @e copy of @a str. - * @param str a NUL-terminated string to scan + * @param yystr a NUL-terminated string to scan * * @return the newly allocated buffer state object. * @note If you want to scan bytes that may contain NUL values, then use diff --git a/scripts/kconfig/lkc_proto.h b/scripts/kconfig/lkc_proto.h index 4d09f6ddefe..8e69461313d 100644 --- a/scripts/kconfig/lkc_proto.h +++ b/scripts/kconfig/lkc_proto.h @@ -21,7 +21,7 @@ P(menu_get_help,const char *,(struct menu *menu)); /* symbol.c */ P(symbol_hash,struct symbol *,[SYMBOL_HASHSIZE]); -P(sym_lookup,struct symbol *,(const char *name, int isconst)); +P(sym_lookup,struct symbol *,(const char *name, int flags)); P(sym_find,struct symbol *,(const char *name)); P(sym_re_search,struct symbol **,(const char *pattern)); P(sym_type_name,const char *,(enum symbol_type type)); diff --git a/scripts/kconfig/lxdialog/inputbox.c b/scripts/kconfig/lxdialog/inputbox.c index 4946bd02b46..616c6013818 100644 --- a/scripts/kconfig/lxdialog/inputbox.c +++ b/scripts/kconfig/lxdialog/inputbox.c @@ -89,7 +89,7 @@ do_resize: box_y = y + 2; box_x = (width - box_width) / 2; draw_box(dialog, y + 1, box_x - 1, 3, box_width + 2, - dlg.border.atr, dlg.dialog.atr); + dlg.dialog.atr, dlg.border.atr); print_buttons(dialog, height, width, 0); diff --git a/scripts/kconfig/menu.c b/scripts/kconfig/menu.c index 606ceb9e746..07ff8d105c9 100644 --- a/scripts/kconfig/menu.c +++ b/scripts/kconfig/menu.c @@ -235,18 +235,22 @@ void menu_finalize(struct menu *parent) sym = parent->sym; if (parent->list) { if (sym && sym_is_choice(sym)) { - /* find the first choice value and find out choice type */ - for (menu = parent->list; menu; menu = menu->next) { - if (menu->sym) { - current_entry = parent; - if (sym->type == S_UNKNOWN) + if (sym->type == S_UNKNOWN) { + /* find the first choice value to find out choice type */ + current_entry = parent; + for (menu = parent->list; menu; menu = menu->next) { + if (menu->sym && menu->sym->type != S_UNKNOWN) { menu_set_type(menu->sym->type); - current_entry = menu; - if (menu->sym->type == S_UNKNOWN) - menu_set_type(sym->type); - break; + break; + } } } + /* set the type of the remaining choice values */ + for (menu = parent->list; menu; menu = menu->next) { + current_entry = menu; + if (menu->sym && menu->sym->type == S_UNKNOWN) + menu_set_type(sym->type); + } parentdep = expr_alloc_symbol(sym); } else if (parent->prompt) parentdep = parent->prompt->visible.expr; @@ -313,50 +317,36 @@ void menu_finalize(struct menu *parent) } } for (menu = parent->list; menu; menu = menu->next) { - if (sym && sym_is_choice(sym) && menu->sym) { + if (sym && sym_is_choice(sym) && + menu->sym && !sym_is_choice_value(menu->sym)) { + current_entry = menu; menu->sym->flags |= SYMBOL_CHOICEVAL; if (!menu->prompt) menu_warn(menu, "choice value must have a prompt"); for (prop = menu->sym->prop; prop; prop = prop->next) { - if (prop->type == P_PROMPT && prop->menu != menu) { - prop_warn(prop, "choice values " - "currently only support a " - "single prompt"); - } if (prop->type == P_DEFAULT) prop_warn(prop, "defaults for choice " - "values not supported"); + "values not supported"); + if (prop->menu == menu) + continue; + if (prop->type == P_PROMPT && + prop->menu->parent->sym != sym) + prop_warn(prop, "choice value used outside its choice group"); } - current_entry = menu; - if (menu->sym->type == S_UNKNOWN) - menu_set_type(sym->type); /* Non-tristate choice values of tristate choices must * depend on the choice being set to Y. The choice * values' dependencies were propagated to their * properties above, so the change here must be re- - * propagated. */ + * propagated. + */ if (sym->type == S_TRISTATE && menu->sym->type != S_TRISTATE) { basedep = expr_alloc_comp(E_EQUAL, sym, &symbol_yes); - basedep = expr_alloc_and(basedep, menu->dep); - basedep = expr_eliminate_dups(basedep); - menu->dep = basedep; + menu->dep = expr_alloc_and(basedep, menu->dep); for (prop = menu->sym->prop; prop; prop = prop->next) { if (prop->menu != menu) continue; - dep = expr_alloc_and(expr_copy(basedep), - prop->visible.expr); - dep = expr_eliminate_dups(dep); - dep = expr_trans_bool(dep); - prop->visible.expr = dep; - if (prop->type == P_SELECT) { - struct symbol *es = prop_get_symbol(prop); - dep2 = expr_alloc_symbol(menu->sym); - dep = expr_alloc_and(dep2, - expr_copy(dep)); - dep = expr_alloc_or(es->rev_dep.expr, dep); - dep = expr_eliminate_dups(dep); - es->rev_dep.expr = dep; - } + prop->visible.expr = expr_alloc_and(expr_copy(basedep), + prop->visible.expr); } } menu_add_symbol(P_CHOICE, sym, NULL); diff --git a/scripts/kconfig/symbol.c b/scripts/kconfig/symbol.c index 4a03191ad17..18f3e5c3363 100644 --- a/scripts/kconfig/symbol.c +++ b/scripts/kconfig/symbol.c @@ -40,7 +40,7 @@ void sym_add_default(struct symbol *sym, const char *def) { struct property *prop = prop_alloc(P_DEFAULT, sym); - prop->expr = expr_alloc_symbol(sym_lookup(def, 1)); + prop->expr = expr_alloc_symbol(sym_lookup(def, SYMBOL_CONST)); } void sym_init(void) @@ -350,9 +350,6 @@ void sym_calc_value(struct symbol *sym) ; } - if (sym->flags & SYMBOL_AUTO) - sym->flags &= ~SYMBOL_WRITE; - sym->curr = newval; if (sym_is_choice(sym) && newval.tri == yes) sym->curr.val = sym_calc_choice(sym); @@ -377,6 +374,9 @@ void sym_calc_value(struct symbol *sym) sym_set_changed(choice_sym); } } + + if (sym->flags & SYMBOL_AUTO) + sym->flags &= ~SYMBOL_WRITE; } void sym_clear_all_valid(void) @@ -651,7 +651,7 @@ bool sym_is_changable(struct symbol *sym) return sym->visible > sym->rev_dep.tri; } -struct symbol *sym_lookup(const char *name, int isconst) +struct symbol *sym_lookup(const char *name, int flags) { struct symbol *symbol; const char *ptr; @@ -671,11 +671,10 @@ struct symbol *sym_lookup(const char *name, int isconst) hash &= 0xff; for (symbol = symbol_hash[hash]; symbol; symbol = symbol->next) { - if (!strcmp(symbol->name, name)) { - if ((isconst && symbol->flags & SYMBOL_CONST) || - (!isconst && !(symbol->flags & SYMBOL_CONST))) - return symbol; - } + if (!strcmp(symbol->name, name) && + (flags ? symbol->flags & flags + : !(symbol->flags & (SYMBOL_CONST|SYMBOL_CHOICE)))) + return symbol; } new_name = strdup(name); } else { @@ -687,8 +686,7 @@ struct symbol *sym_lookup(const char *name, int isconst) memset(symbol, 0, sizeof(*symbol)); symbol->name = new_name; symbol->type = S_UNKNOWN; - if (isconst) - symbol->flags |= SYMBOL_CONST; + symbol->flags |= flags; symbol->next = symbol_hash[hash]; symbol_hash[hash] = symbol; @@ -762,8 +760,6 @@ struct symbol **sym_re_search(const char *pattern) } -struct symbol *sym_check_deps(struct symbol *sym); - static struct symbol *sym_check_expr_deps(struct expr *e) { struct symbol *sym; @@ -795,40 +791,100 @@ static struct symbol *sym_check_expr_deps(struct expr *e) } /* return NULL when dependencies are OK */ -struct symbol *sym_check_deps(struct symbol *sym) +static struct symbol *sym_check_sym_deps(struct symbol *sym) { struct symbol *sym2; struct property *prop; - if (sym->flags & SYMBOL_CHECK) { - fprintf(stderr, "%s:%d:error: found recursive dependency: %s", - sym->prop->file->name, sym->prop->lineno, sym->name); - return sym; - } - if (sym->flags & SYMBOL_CHECKED) - return NULL; - - sym->flags |= (SYMBOL_CHECK | SYMBOL_CHECKED); sym2 = sym_check_expr_deps(sym->rev_dep.expr); if (sym2) - goto out; + return sym2; for (prop = sym->prop; prop; prop = prop->next) { if (prop->type == P_CHOICE || prop->type == P_SELECT) continue; sym2 = sym_check_expr_deps(prop->visible.expr); if (sym2) - goto out; + break; if (prop->type != P_DEFAULT || sym_is_choice(sym)) continue; sym2 = sym_check_expr_deps(prop->expr); if (sym2) - goto out; + break; } -out: + + return sym2; +} + +static struct symbol *sym_check_choice_deps(struct symbol *choice) +{ + struct symbol *sym, *sym2; + struct property *prop; + struct expr *e; + + prop = sym_get_choice_prop(choice); + expr_list_for_each_sym(prop->expr, e, sym) + sym->flags |= (SYMBOL_CHECK | SYMBOL_CHECKED); + + choice->flags |= (SYMBOL_CHECK | SYMBOL_CHECKED); + sym2 = sym_check_sym_deps(choice); + choice->flags &= ~SYMBOL_CHECK; if (sym2) - fprintf(stderr, " -> %s%s", sym->name, sym2 == sym? "\n": ""); - sym->flags &= ~SYMBOL_CHECK; + goto out; + + expr_list_for_each_sym(prop->expr, e, sym) { + sym2 = sym_check_sym_deps(sym); + if (sym2) { + fprintf(stderr, " -> %s", sym->name); + break; + } + } +out: + expr_list_for_each_sym(prop->expr, e, sym) + sym->flags &= ~SYMBOL_CHECK; + + if (sym2 && sym_is_choice_value(sym2) && + prop_get_symbol(sym_get_choice_prop(sym2)) == choice) + sym2 = choice; + + return sym2; +} + +struct symbol *sym_check_deps(struct symbol *sym) +{ + struct symbol *sym2; + struct property *prop; + + if (sym->flags & SYMBOL_CHECK) { + fprintf(stderr, "%s:%d:error: found recursive dependency: %s", + sym->prop->file->name, sym->prop->lineno, + sym->name ? sym->name : "<choice>"); + return sym; + } + if (sym->flags & SYMBOL_CHECKED) + return NULL; + + if (sym_is_choice_value(sym)) { + /* for choice groups start the check with main choice symbol */ + prop = sym_get_choice_prop(sym); + sym2 = sym_check_deps(prop_get_symbol(prop)); + } else if (sym_is_choice(sym)) { + sym2 = sym_check_choice_deps(sym); + } else { + sym->flags |= (SYMBOL_CHECK | SYMBOL_CHECKED); + sym2 = sym_check_sym_deps(sym); + sym->flags &= ~SYMBOL_CHECK; + } + + if (sym2) { + fprintf(stderr, " -> %s", sym->name ? sym->name : "<choice>"); + if (sym2 == sym) { + fprintf(stderr, "\n"); + zconfnerrs++; + sym2 = NULL; + } + } + return sym2; } @@ -904,7 +960,7 @@ void prop_add_env(const char *env) } prop = prop_alloc(P_ENV, sym); - prop->expr = expr_alloc_symbol(sym_lookup(env, 1)); + prop->expr = expr_alloc_symbol(sym_lookup(env, SYMBOL_CONST)); sym_env_list = expr_alloc_one(E_LIST, sym_env_list); sym_env_list->right.sym = sym; diff --git a/scripts/kconfig/zconf.tab.c_shipped b/scripts/kconfig/zconf.tab.c_shipped index d22d92496f2..95df833b5a9 100644 --- a/scripts/kconfig/zconf.tab.c_shipped +++ b/scripts/kconfig/zconf.tab.c_shipped @@ -446,16 +446,16 @@ union yyalloc /* YYFINAL -- State number of the termination state. */ #define YYFINAL 3 /* YYLAST -- Last index in YYTABLE. */ -#define YYLAST 258 +#define YYLAST 259 /* YYNTOKENS -- Number of terminals. */ #define YYNTOKENS 35 /* YYNNTS -- Number of nonterminals. */ -#define YYNNTS 45 +#define YYNNTS 46 /* YYNRULES -- Number of rules. */ -#define YYNRULES 108 +#define YYNRULES 110 /* YYNRULES -- Number of states. */ -#define YYNSTATES 178 +#define YYNSTATES 180 /* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX. */ #define YYUNDEFTOK 2 @@ -507,13 +507,14 @@ static const yytype_uint16 yyprhs[] = 28, 33, 37, 39, 41, 43, 45, 47, 49, 51, 53, 55, 57, 59, 61, 63, 67, 70, 74, 77, 81, 84, 85, 88, 91, 94, 97, 100, 103, 107, - 112, 117, 122, 128, 132, 133, 137, 138, 141, 144, - 147, 149, 153, 154, 157, 160, 163, 166, 169, 174, - 178, 181, 186, 187, 190, 194, 196, 200, 201, 204, - 207, 210, 214, 217, 219, 223, 224, 227, 230, 233, - 237, 241, 244, 247, 250, 251, 254, 257, 260, 265, - 266, 269, 271, 273, 276, 279, 282, 284, 287, 288, - 291, 293, 297, 301, 305, 308, 312, 316, 318 + 112, 117, 122, 128, 132, 133, 137, 138, 141, 145, + 148, 150, 154, 155, 158, 161, 164, 167, 170, 175, + 179, 182, 187, 188, 191, 195, 197, 201, 202, 205, + 208, 211, 215, 218, 220, 224, 225, 228, 231, 234, + 238, 242, 245, 248, 251, 252, 255, 258, 261, 266, + 267, 270, 272, 274, 277, 280, 283, 285, 288, 289, + 292, 294, 298, 302, 306, 309, 313, 317, 319, 321, + 322 }; /* YYRHS -- A `-1'-separated list of the rules' RHS. */ @@ -533,24 +534,25 @@ static const yytype_int8 yyrhs[] = 30, -1, 20, 78, 77, 30, -1, 21, 25, 77, 30, -1, 22, 79, 79, 77, 30, -1, 23, 48, 30, -1, -1, 48, 25, 49, -1, -1, 33, 74, - -1, 7, 30, -1, 50, 54, -1, 75, -1, 51, - 56, 52, -1, -1, 54, 55, -1, 54, 72, -1, - 54, 70, -1, 54, 30, -1, 54, 40, -1, 18, - 74, 77, 30, -1, 19, 73, 30, -1, 17, 30, - -1, 20, 25, 77, 30, -1, -1, 56, 39, -1, - 14, 78, 76, -1, 75, -1, 57, 60, 58, -1, - -1, 60, 39, -1, 60, 64, -1, 60, 53, -1, - 4, 74, 30, -1, 61, 71, -1, 75, -1, 62, - 65, 63, -1, -1, 65, 39, -1, 65, 64, -1, - 65, 53, -1, 6, 74, 30, -1, 9, 74, 30, - -1, 67, 71, -1, 12, 30, -1, 69, 13, -1, - -1, 71, 72, -1, 71, 30, -1, 71, 40, -1, - 16, 24, 78, 30, -1, -1, 74, 77, -1, 25, - -1, 26, -1, 5, 30, -1, 8, 30, -1, 15, - 30, -1, 30, -1, 76, 30, -1, -1, 14, 78, - -1, 79, -1, 79, 33, 79, -1, 79, 27, 79, - -1, 29, 78, 28, -1, 34, 78, -1, 78, 31, - 78, -1, 78, 32, 78, -1, 25, -1, 26, -1 + -1, 7, 80, 30, -1, 50, 54, -1, 75, -1, + 51, 56, 52, -1, -1, 54, 55, -1, 54, 72, + -1, 54, 70, -1, 54, 30, -1, 54, 40, -1, + 18, 74, 77, 30, -1, 19, 73, 30, -1, 17, + 30, -1, 20, 25, 77, 30, -1, -1, 56, 39, + -1, 14, 78, 76, -1, 75, -1, 57, 60, 58, + -1, -1, 60, 39, -1, 60, 64, -1, 60, 53, + -1, 4, 74, 30, -1, 61, 71, -1, 75, -1, + 62, 65, 63, -1, -1, 65, 39, -1, 65, 64, + -1, 65, 53, -1, 6, 74, 30, -1, 9, 74, + 30, -1, 67, 71, -1, 12, 30, -1, 69, 13, + -1, -1, 71, 72, -1, 71, 30, -1, 71, 40, + -1, 16, 24, 78, 30, -1, -1, 74, 77, -1, + 25, -1, 26, -1, 5, 30, -1, 8, 30, -1, + 15, 30, -1, 30, -1, 76, 30, -1, -1, 14, + 78, -1, 79, -1, 79, 33, 79, -1, 79, 27, + 79, -1, 29, 78, 28, -1, 34, 78, -1, 78, + 31, 78, -1, 78, 32, 78, -1, 25, -1, 26, + -1, -1, 25, -1 }; /* YYRLINE[YYN] -- source line where rule number YYN was defined. */ @@ -566,7 +568,8 @@ static const yytype_uint16 yyrline[] = 339, 344, 351, 356, 364, 367, 369, 370, 371, 374, 382, 389, 396, 402, 409, 411, 412, 413, 416, 424, 426, 431, 432, 435, 436, 437, 441, 442, 445, 446, - 449, 450, 451, 452, 453, 454, 455, 458, 459 + 449, 450, 451, 452, 453, 454, 455, 458, 459, 462, + 463 }; #endif @@ -590,7 +593,8 @@ static const char *const yytname[] = "if_entry", "if_end", "if_stmt", "if_block", "menu", "menu_entry", "menu_end", "menu_stmt", "menu_block", "source_stmt", "comment", "comment_stmt", "help_start", "help", "depends_list", "depends", - "prompt_stmt_opt", "prompt", "end", "nl", "if_expr", "expr", "symbol", 0 + "prompt_stmt_opt", "prompt", "end", "nl", "if_expr", "expr", "symbol", + "word_opt", 0 }; #endif @@ -619,7 +623,8 @@ static const yytype_uint8 yyr1[] = 60, 61, 62, 63, 64, 65, 65, 65, 65, 66, 67, 68, 69, 70, 71, 71, 71, 71, 72, 73, 73, 74, 74, 75, 75, 75, 76, 76, 77, 77, - 78, 78, 78, 78, 78, 78, 78, 79, 79 + 78, 78, 78, 78, 78, 78, 78, 79, 79, 80, + 80 }; /* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */ @@ -629,13 +634,14 @@ static const yytype_uint8 yyr2[] = 4, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 2, 3, 2, 3, 2, 0, 2, 2, 2, 2, 2, 2, 3, 4, - 4, 4, 5, 3, 0, 3, 0, 2, 2, 2, + 4, 4, 5, 3, 0, 3, 0, 2, 3, 2, 1, 3, 0, 2, 2, 2, 2, 2, 4, 3, 2, 4, 0, 2, 3, 1, 3, 0, 2, 2, 2, 3, 2, 1, 3, 0, 2, 2, 2, 3, 3, 2, 2, 2, 0, 2, 2, 2, 4, 0, 2, 1, 1, 2, 2, 2, 1, 2, 0, 2, - 1, 3, 3, 3, 2, 3, 3, 1, 1 + 1, 3, 3, 3, 2, 3, 3, 1, 1, 0, + 1 }; /* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state @@ -643,69 +649,69 @@ static const yytype_uint8 yyr2[] = means the default is an error. */ static const yytype_uint8 yydefact[] = { - 3, 0, 0, 1, 0, 0, 0, 0, 0, 0, + 3, 0, 0, 1, 0, 0, 0, 0, 0, 109, 0, 0, 0, 0, 0, 0, 12, 16, 13, 14, 18, 15, 17, 0, 19, 0, 4, 31, 22, 31, 23, 52, 62, 5, 67, 20, 84, 75, 6, 24, 84, 21, 8, 11, 91, 92, 0, 0, 93, 0, - 48, 94, 0, 0, 0, 107, 108, 0, 0, 0, - 100, 95, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 96, 7, 71, 79, 80, 27, 29, 0, - 104, 0, 0, 64, 0, 0, 9, 10, 0, 0, - 0, 0, 89, 0, 0, 0, 44, 0, 37, 36, - 32, 33, 0, 35, 34, 0, 0, 89, 0, 56, - 57, 53, 55, 54, 63, 51, 50, 68, 70, 66, - 69, 65, 86, 87, 85, 76, 78, 74, 77, 73, - 97, 103, 105, 106, 102, 101, 26, 82, 0, 98, - 0, 98, 98, 98, 0, 0, 0, 83, 60, 98, - 0, 98, 0, 0, 0, 38, 90, 0, 0, 98, - 46, 43, 25, 0, 59, 0, 88, 99, 39, 40, - 41, 0, 0, 45, 58, 61, 42, 47 + 110, 0, 94, 0, 0, 0, 107, 108, 0, 0, + 0, 100, 95, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 96, 7, 71, 79, 48, 80, 27, + 29, 0, 104, 0, 0, 64, 0, 0, 9, 10, + 0, 0, 0, 0, 89, 0, 0, 0, 44, 0, + 37, 36, 32, 33, 0, 35, 34, 0, 0, 89, + 0, 56, 57, 53, 55, 54, 63, 51, 50, 68, + 70, 66, 69, 65, 86, 87, 85, 76, 78, 74, + 77, 73, 97, 103, 105, 106, 102, 101, 26, 82, + 0, 98, 0, 98, 98, 98, 0, 0, 0, 83, + 60, 98, 0, 98, 0, 0, 0, 38, 90, 0, + 0, 98, 46, 43, 25, 0, 59, 0, 88, 99, + 39, 40, 41, 0, 0, 45, 58, 61, 42, 47 }; /* YYDEFGOTO[NTERM-NUM]. */ static const yytype_int16 yydefgoto[] = { - -1, 1, 2, 25, 26, 99, 27, 28, 29, 30, - 64, 100, 101, 145, 173, 31, 32, 115, 33, 66, - 111, 67, 34, 119, 35, 68, 36, 37, 127, 38, - 70, 39, 40, 41, 102, 103, 69, 104, 140, 141, - 42, 73, 154, 59, 60 + -1, 1, 2, 25, 26, 101, 27, 28, 29, 30, + 65, 102, 103, 147, 175, 31, 32, 117, 33, 67, + 113, 68, 34, 121, 35, 69, 36, 37, 129, 38, + 71, 39, 40, 41, 104, 105, 70, 106, 142, 143, + 42, 74, 156, 60, 61, 51 }; /* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing STATE-NUM. */ -#define YYPACT_NINF -78 +#define YYPACT_NINF -80 static const yytype_int16 yypact[] = { - -78, 33, 130, -78, -28, 73, 73, 7, 73, 36, - 41, 73, 26, 52, -4, 58, -78, -78, -78, -78, - -78, -78, -78, 90, -78, 94, -78, -78, -78, -78, - -78, -78, -78, -78, -78, -78, -78, -78, -78, -78, - -78, -78, -78, -78, -78, -78, 74, 85, -78, 96, - -78, -78, 131, 134, 147, -78, -78, -4, -4, 193, - -10, -78, 162, 164, 38, 102, 64, 148, 5, 192, - 5, 165, -78, 174, -78, -78, -78, -78, -78, 65, - -78, -4, -4, 174, 103, 103, -78, -78, 175, 185, - 197, 73, 73, -4, 194, 103, -78, 231, -78, -78, - -78, -78, 220, -78, -78, 204, 73, 73, 210, -78, - -78, -78, -78, -78, -78, -78, -78, -78, -78, -78, - -78, -78, -78, -78, -78, -78, -78, -78, -78, -78, - -78, -78, 205, -78, -78, -78, -78, -78, -4, 222, - 208, 222, 195, 222, 103, 2, 209, -78, -78, 222, - 211, 222, 199, -4, 212, -78, -78, 213, 214, 222, - 207, -78, -78, 215, -78, 216, -78, 111, -78, -78, - -78, 217, 73, -78, -78, -78, -78, -78 + -80, 2, 132, -80, -13, -1, -1, -2, -1, 9, + 33, -1, 27, 40, -3, 38, -80, -80, -80, -80, + -80, -80, -80, 71, -80, 77, -80, -80, -80, -80, + -80, -80, -80, -80, -80, -80, -80, -80, -80, -80, + -80, -80, -80, -80, -80, -80, 57, 61, -80, 63, + -80, 76, -80, 87, 101, 133, -80, -80, -3, -3, + 195, -6, -80, 136, 149, 39, 104, 65, 150, 5, + 194, 5, 167, -80, 176, -80, -80, -80, -80, -80, + -80, 68, -80, -3, -3, 176, 72, 72, -80, -80, + 177, 187, 78, -1, -1, -3, 196, 72, -80, 222, + -80, -80, -80, -80, 221, -80, -80, 205, -1, -1, + 211, -80, -80, -80, -80, -80, -80, -80, -80, -80, + -80, -80, -80, -80, -80, -80, -80, -80, -80, -80, + -80, -80, -80, -80, 206, -80, -80, -80, -80, -80, + -3, 223, 209, 223, 197, 223, 72, 7, 210, -80, + -80, 223, 212, 223, 201, -3, 213, -80, -80, 214, + 215, 223, 208, -80, -80, 216, -80, 217, -80, 113, + -80, -80, -80, 218, -1, -80, -80, -80, -80, -80 }; /* YYPGOTO[NTERM-NUM]. */ static const yytype_int16 yypgoto[] = { - -78, -78, -78, -78, 121, -35, -78, -78, -78, -78, - 219, -78, -78, -78, -78, -78, -78, -78, -44, -78, - -78, -78, -78, -78, -78, -78, -78, -78, -78, -6, - -78, -78, -78, -78, -78, 183, 218, 21, 143, -5, - 146, 196, 69, -53, -77 + -80, -80, -80, -80, 122, -34, -80, -80, -80, -80, + 220, -80, -80, -80, -80, -80, -80, -80, 59, -80, + -80, -80, -80, -80, -80, -80, -80, -80, -80, 125, + -80, -80, -80, -80, -80, 183, 219, 22, 142, -5, + 147, 192, 69, -54, -79, -80 }; /* YYTABLE[YYPACT[STATE-NUM]]. What to do in state STATE-NUM. If @@ -715,62 +721,62 @@ static const yytype_int16 yypgoto[] = #define YYTABLE_NINF -82 static const yytype_int16 yytable[] = { - 46, 47, 43, 49, 79, 80, 52, 134, 135, 6, - 7, 8, 9, 10, 11, 12, 13, 84, 144, 14, - 15, 55, 56, 85, 118, 57, 126, 160, 132, 133, - 58, 110, 161, 3, 123, 24, 123, 48, -28, 88, - 142, -28, -28, -28, -28, -28, -28, -28, -28, -28, - 89, 53, -28, -28, 90, -28, 91, 92, 93, 94, - 95, 96, 120, 97, 128, 88, 50, 159, 98, -49, - -49, 51, -49, -49, -49, -49, 89, 54, -49, -49, - 90, 105, 106, 107, 108, 152, 139, 113, 61, 97, - 124, 62, 124, 131, 109, 63, 81, 82, 44, 45, - 167, 149, -30, 88, 72, -30, -30, -30, -30, -30, - -30, -30, -30, -30, 89, 74, -30, -30, 90, -30, - 91, 92, 93, 94, 95, 96, 75, 97, 55, 56, - -2, 4, 98, 5, 6, 7, 8, 9, 10, 11, - 12, 13, 81, 82, 14, 15, 16, 17, 18, 19, - 20, 21, 22, 7, 8, 23, 10, 11, 12, 13, - 24, 76, 14, 15, 77, -81, 88, 177, -81, -81, - -81, -81, -81, -81, -81, -81, -81, 78, 24, -81, - -81, 90, -81, -81, -81, -81, -81, -81, 114, 117, - 97, 125, 86, 88, 87, 122, -72, -72, -72, -72, - -72, -72, -72, -72, 130, 136, -72, -72, 90, 153, - 156, 157, 158, 116, 121, 137, 129, 97, 163, 143, - 165, 138, 122, 72, 81, 82, 81, 82, 171, 166, - 81, 82, 146, 147, 148, 151, 153, 82, 155, 162, - 172, 164, 168, 169, 170, 174, 175, 176, 65, 112, - 150, 0, 0, 0, 0, 83, 0, 0, 71 + 46, 47, 3, 49, 81, 82, 53, 136, 137, 6, + 7, 8, 9, 10, 11, 12, 13, 43, 146, 14, + 15, 86, 56, 57, 44, 45, 58, 87, 48, 134, + 135, 59, 162, 112, 50, 24, 125, 163, 125, -28, + 90, 144, -28, -28, -28, -28, -28, -28, -28, -28, + -28, 91, 54, -28, -28, 92, -28, 93, 94, 95, + 96, 97, 98, 52, 99, 55, 90, 161, 62, 100, + -49, -49, 63, -49, -49, -49, -49, 91, 64, -49, + -49, 92, 107, 108, 109, 110, 154, 73, 141, 115, + 99, 75, 126, 76, 126, 111, 133, 56, 57, 83, + 84, 169, 140, 151, -30, 90, 77, -30, -30, -30, + -30, -30, -30, -30, -30, -30, 91, 78, -30, -30, + 92, -30, 93, 94, 95, 96, 97, 98, 120, 99, + 128, 79, -2, 4, 100, 5, 6, 7, 8, 9, + 10, 11, 12, 13, 83, 84, 14, 15, 16, 17, + 18, 19, 20, 21, 22, 7, 8, 23, 10, 11, + 12, 13, 24, 80, 14, 15, 88, -81, 90, 179, + -81, -81, -81, -81, -81, -81, -81, -81, -81, 89, + 24, -81, -81, 92, -81, -81, -81, -81, -81, -81, + 116, 119, 99, 127, 122, 90, 130, 124, -72, -72, + -72, -72, -72, -72, -72, -72, 132, 138, -72, -72, + 92, 155, 158, 159, 160, 118, 123, 139, 131, 99, + 165, 145, 167, 148, 124, 73, 83, 84, 83, 84, + 173, 168, 83, 84, 149, 150, 153, 155, 84, 157, + 164, 174, 166, 170, 171, 172, 176, 177, 178, 66, + 114, 152, 85, 0, 0, 0, 0, 0, 0, 72 }; static const yytype_int16 yycheck[] = { - 5, 6, 30, 8, 57, 58, 11, 84, 85, 4, - 5, 6, 7, 8, 9, 10, 11, 27, 95, 14, - 15, 25, 26, 33, 68, 29, 70, 25, 81, 82, - 34, 66, 30, 0, 69, 30, 71, 30, 0, 1, - 93, 3, 4, 5, 6, 7, 8, 9, 10, 11, - 12, 25, 14, 15, 16, 17, 18, 19, 20, 21, - 22, 23, 68, 25, 70, 1, 30, 144, 30, 5, - 6, 30, 8, 9, 10, 11, 12, 25, 14, 15, - 16, 17, 18, 19, 20, 138, 91, 66, 30, 25, - 69, 1, 71, 28, 30, 1, 31, 32, 25, 26, - 153, 106, 0, 1, 30, 3, 4, 5, 6, 7, - 8, 9, 10, 11, 12, 30, 14, 15, 16, 17, - 18, 19, 20, 21, 22, 23, 30, 25, 25, 26, - 0, 1, 30, 3, 4, 5, 6, 7, 8, 9, - 10, 11, 31, 32, 14, 15, 16, 17, 18, 19, - 20, 21, 22, 5, 6, 25, 8, 9, 10, 11, - 30, 30, 14, 15, 30, 0, 1, 172, 3, 4, - 5, 6, 7, 8, 9, 10, 11, 30, 30, 14, - 15, 16, 17, 18, 19, 20, 21, 22, 67, 68, - 25, 70, 30, 1, 30, 30, 4, 5, 6, 7, - 8, 9, 10, 11, 30, 30, 14, 15, 16, 14, - 141, 142, 143, 67, 68, 30, 70, 25, 149, 25, - 151, 24, 30, 30, 31, 32, 31, 32, 159, 30, - 31, 32, 1, 13, 30, 25, 14, 32, 30, 30, - 33, 30, 30, 30, 30, 30, 30, 30, 29, 66, - 107, -1, -1, -1, -1, 59, -1, -1, 40 + 5, 6, 0, 8, 58, 59, 11, 86, 87, 4, + 5, 6, 7, 8, 9, 10, 11, 30, 97, 14, + 15, 27, 25, 26, 25, 26, 29, 33, 30, 83, + 84, 34, 25, 67, 25, 30, 70, 30, 72, 0, + 1, 95, 3, 4, 5, 6, 7, 8, 9, 10, + 11, 12, 25, 14, 15, 16, 17, 18, 19, 20, + 21, 22, 23, 30, 25, 25, 1, 146, 30, 30, + 5, 6, 1, 8, 9, 10, 11, 12, 1, 14, + 15, 16, 17, 18, 19, 20, 140, 30, 93, 67, + 25, 30, 70, 30, 72, 30, 28, 25, 26, 31, + 32, 155, 24, 108, 0, 1, 30, 3, 4, 5, + 6, 7, 8, 9, 10, 11, 12, 30, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, 69, 25, + 71, 30, 0, 1, 30, 3, 4, 5, 6, 7, + 8, 9, 10, 11, 31, 32, 14, 15, 16, 17, + 18, 19, 20, 21, 22, 5, 6, 25, 8, 9, + 10, 11, 30, 30, 14, 15, 30, 0, 1, 174, + 3, 4, 5, 6, 7, 8, 9, 10, 11, 30, + 30, 14, 15, 16, 17, 18, 19, 20, 21, 22, + 68, 69, 25, 71, 69, 1, 71, 30, 4, 5, + 6, 7, 8, 9, 10, 11, 30, 30, 14, 15, + 16, 14, 143, 144, 145, 68, 69, 30, 71, 25, + 151, 25, 153, 1, 30, 30, 31, 32, 31, 32, + 161, 30, 31, 32, 13, 30, 25, 14, 32, 30, + 30, 33, 30, 30, 30, 30, 30, 30, 30, 29, + 67, 109, 60, -1, -1, -1, -1, -1, -1, 40 }; /* YYSTOS[STATE-NUM] -- The (internal number of the) accessing @@ -782,19 +788,19 @@ static const yytype_uint8 yystos[] = 20, 21, 22, 25, 30, 38, 39, 41, 42, 43, 44, 50, 51, 53, 57, 59, 61, 62, 64, 66, 67, 68, 75, 30, 25, 26, 74, 74, 30, 74, - 30, 30, 74, 25, 25, 25, 26, 29, 34, 78, - 79, 30, 1, 1, 45, 45, 54, 56, 60, 71, - 65, 71, 30, 76, 30, 30, 30, 30, 30, 78, - 78, 31, 32, 76, 27, 33, 30, 30, 1, 12, - 16, 18, 19, 20, 21, 22, 23, 25, 30, 40, - 46, 47, 69, 70, 72, 17, 18, 19, 20, 30, - 40, 55, 70, 72, 39, 52, 75, 39, 53, 58, - 64, 75, 30, 40, 72, 39, 53, 63, 64, 75, - 30, 28, 78, 78, 79, 79, 30, 30, 24, 74, - 73, 74, 78, 25, 79, 48, 1, 13, 30, 74, - 73, 25, 78, 14, 77, 30, 77, 77, 77, 79, - 25, 30, 30, 77, 30, 77, 30, 78, 30, 30, - 30, 77, 33, 49, 30, 30, 30, 74 + 25, 80, 30, 74, 25, 25, 25, 26, 29, 34, + 78, 79, 30, 1, 1, 45, 45, 54, 56, 60, + 71, 65, 71, 30, 76, 30, 30, 30, 30, 30, + 30, 78, 78, 31, 32, 76, 27, 33, 30, 30, + 1, 12, 16, 18, 19, 20, 21, 22, 23, 25, + 30, 40, 46, 47, 69, 70, 72, 17, 18, 19, + 20, 30, 40, 55, 70, 72, 39, 52, 75, 39, + 53, 58, 64, 75, 30, 40, 72, 39, 53, 63, + 64, 75, 30, 28, 78, 78, 79, 79, 30, 30, + 24, 74, 73, 74, 78, 25, 79, 48, 1, 13, + 30, 74, 73, 25, 78, 14, 77, 30, 77, 77, + 77, 79, 25, 30, 30, 77, 30, 77, 30, 78, + 30, 30, 30, 77, 33, 49, 30, 30, 30, 74 }; #define yyerrok (yyerrstatus = 0) @@ -1781,8 +1787,8 @@ yyreduce: case 48: { - struct symbol *sym = sym_lookup(NULL, 0); - sym->flags |= SYMBOL_CHOICE; + struct symbol *sym = sym_lookup((yyvsp[(2) - (3)].string), SYMBOL_CHOICE); + sym->flags |= SYMBOL_AUTO; menu_add_entry(sym); menu_add_expr(P_CHOICE, NULL, NULL); printd(DEBUG_PARSE, "%s:%d:choice\n", zconf_curname(), zconf_lineno()); @@ -2014,7 +2020,12 @@ yyreduce: case 108: - { (yyval.symbol) = sym_lookup((yyvsp[(1) - (1)].string), 1); free((yyvsp[(1) - (1)].string)); ;} + { (yyval.symbol) = sym_lookup((yyvsp[(1) - (1)].string), SYMBOL_CONST); free((yyvsp[(1) - (1)].string)); ;} + break; + + case 109: + + { (yyval.string) = NULL; ;} break; diff --git a/scripts/kconfig/zconf.y b/scripts/kconfig/zconf.y index d9b96ba8e38..9710b82466f 100644 --- a/scripts/kconfig/zconf.y +++ b/scripts/kconfig/zconf.y @@ -91,7 +91,7 @@ static struct menu *current_menu, *current_entry; %type <id> end %type <id> option_name %type <menu> if_entry menu_entry choice_entry -%type <string> symbol_option_arg +%type <string> symbol_option_arg word_opt %destructor { fprintf(stderr, "%s:%d: missing end statement for this entry\n", @@ -239,10 +239,10 @@ symbol_option_arg: /* choice entry */ -choice: T_CHOICE T_EOL +choice: T_CHOICE word_opt T_EOL { - struct symbol *sym = sym_lookup(NULL, 0); - sym->flags |= SYMBOL_CHOICE; + struct symbol *sym = sym_lookup($2, SYMBOL_CHOICE); + sym->flags |= SYMBOL_AUTO; menu_add_entry(sym); menu_add_expr(P_CHOICE, NULL, NULL); printd(DEBUG_PARSE, "%s:%d:choice\n", zconf_curname(), zconf_lineno()); @@ -456,9 +456,12 @@ expr: symbol { $$ = expr_alloc_symbol($1); } ; symbol: T_WORD { $$ = sym_lookup($1, 0); free($1); } - | T_WORD_QUOTE { $$ = sym_lookup($1, 1); free($1); } + | T_WORD_QUOTE { $$ = sym_lookup($1, SYMBOL_CONST); free($1); } ; +word_opt: /* empty */ { $$ = NULL; } + | T_WORD + %% void conf_parse(const char *name) |