diff options
-rw-r--r-- | mm/slub.c | 96 |
1 files changed, 81 insertions, 15 deletions
@@ -1586,13 +1586,16 @@ static int calculate_order(int size) | |||
1586 | order < MAX_ORDER; order++) { | 1586 | order < MAX_ORDER; order++) { |
1587 | unsigned long slab_size = PAGE_SIZE << order; | 1587 | unsigned long slab_size = PAGE_SIZE << order; |
1588 | 1588 | ||
1589 | if (slub_max_order > order && | 1589 | if (order < slub_max_order && |
1590 | slab_size < slub_min_objects * size) | 1590 | slab_size < slub_min_objects * size) |
1591 | continue; | 1591 | continue; |
1592 | 1592 | ||
1593 | if (slab_size < size) | 1593 | if (slab_size < size) |
1594 | continue; | 1594 | continue; |
1595 | 1595 | ||
1596 | if (order >= slub_max_order) | ||
1597 | break; | ||
1598 | |||
1596 | rem = slab_size % size; | 1599 | rem = slab_size % size; |
1597 | 1600 | ||
1598 | if (rem <= slab_size / 8) | 1601 | if (rem <= slab_size / 8) |
@@ -2751,6 +2754,13 @@ static void resiliency_test(void) {}; | |||
2751 | struct location { | 2754 | struct location { |
2752 | unsigned long count; | 2755 | unsigned long count; |
2753 | void *addr; | 2756 | void *addr; |
2757 | long long sum_time; | ||
2758 | long min_time; | ||
2759 | long max_time; | ||
2760 | long min_pid; | ||
2761 | long max_pid; | ||
2762 | cpumask_t cpus; | ||
2763 | nodemask_t nodes; | ||
2754 | }; | 2764 | }; |
2755 | 2765 | ||
2756 | struct loc_track { | 2766 | struct loc_track { |
@@ -2791,11 +2801,12 @@ static int alloc_loc_track(struct loc_track *t, unsigned long max) | |||
2791 | } | 2801 | } |
2792 | 2802 | ||
2793 | static int add_location(struct loc_track *t, struct kmem_cache *s, | 2803 | static int add_location(struct loc_track *t, struct kmem_cache *s, |
2794 | void *addr) | 2804 | const struct track *track) |
2795 | { | 2805 | { |
2796 | long start, end, pos; | 2806 | long start, end, pos; |
2797 | struct location *l; | 2807 | struct location *l; |
2798 | void *caddr; | 2808 | void *caddr; |
2809 | unsigned long age = jiffies - track->when; | ||
2799 | 2810 | ||
2800 | start = -1; | 2811 | start = -1; |
2801 | end = t->count; | 2812 | end = t->count; |
@@ -2811,12 +2822,29 @@ static int add_location(struct loc_track *t, struct kmem_cache *s, | |||
2811 | break; | 2822 | break; |
2812 | 2823 | ||
2813 | caddr = t->loc[pos].addr; | 2824 | caddr = t->loc[pos].addr; |
2814 | if (addr == caddr) { | 2825 | if (track->addr == caddr) { |
2815 | t->loc[pos].count++; | 2826 | |
2827 | l = &t->loc[pos]; | ||
2828 | l->count++; | ||
2829 | if (track->when) { | ||
2830 | l->sum_time += age; | ||
2831 | if (age < l->min_time) | ||
2832 | l->min_time = age; | ||
2833 | if (age > l->max_time) | ||
2834 | l->max_time = age; | ||
2835 | |||
2836 | if (track->pid < l->min_pid) | ||
2837 | l->min_pid = track->pid; | ||
2838 | if (track->pid > l->max_pid) | ||
2839 | l->max_pid = track->pid; | ||
2840 | |||
2841 | cpu_set(track->cpu, l->cpus); | ||
2842 | } | ||
2843 | node_set(page_to_nid(virt_to_page(track)), l->nodes); | ||
2816 | return 1; | 2844 | return 1; |
2817 | } | 2845 | } |
2818 | 2846 | ||
2819 | if (addr < caddr) | 2847 | if (track->addr < caddr) |
2820 | end = pos; | 2848 | end = pos; |
2821 | else | 2849 | else |
2822 | start = pos; | 2850 | start = pos; |
@@ -2834,7 +2862,16 @@ static int add_location(struct loc_track *t, struct kmem_cache *s, | |||
2834 | (t->count - pos) * sizeof(struct location)); | 2862 | (t->count - pos) * sizeof(struct location)); |
2835 | t->count++; | 2863 | t->count++; |
2836 | l->count = 1; | 2864 | l->count = 1; |
2837 | l->addr = addr; | 2865 | l->addr = track->addr; |
2866 | l->sum_time = age; | ||
2867 | l->min_time = age; | ||
2868 | l->max_time = age; | ||
2869 | l->min_pid = track->pid; | ||
2870 | l->max_pid = track->pid; | ||
2871 | cpus_clear(l->cpus); | ||
2872 | cpu_set(track->cpu, l->cpus); | ||
2873 | nodes_clear(l->nodes); | ||
2874 | node_set(page_to_nid(virt_to_page(track)), l->nodes); | ||
2838 | return 1; | 2875 | return 1; |
2839 | } | 2876 | } |
2840 | 2877 | ||
@@ -2850,11 +2887,8 @@ static void process_slab(struct loc_track *t, struct kmem_cache *s, | |||
2850 | set_bit(slab_index(p, s, addr), map); | 2887 | set_bit(slab_index(p, s, addr), map); |
2851 | 2888 | ||
2852 | for_each_object(p, s, addr) | 2889 | for_each_object(p, s, addr) |
2853 | if (!test_bit(slab_index(p, s, addr), map)) { | 2890 | if (!test_bit(slab_index(p, s, addr), map)) |
2854 | void *addr = get_track(s, p, alloc)->addr; | 2891 | add_location(t, s, get_track(s, p, alloc)); |
2855 | |||
2856 | add_location(t, s, addr); | ||
2857 | } | ||
2858 | } | 2892 | } |
2859 | 2893 | ||
2860 | static int list_locations(struct kmem_cache *s, char *buf, | 2894 | static int list_locations(struct kmem_cache *s, char *buf, |
@@ -2888,15 +2922,47 @@ static int list_locations(struct kmem_cache *s, char *buf, | |||
2888 | } | 2922 | } |
2889 | 2923 | ||
2890 | for (i = 0; i < t.count; i++) { | 2924 | for (i = 0; i < t.count; i++) { |
2891 | void *addr = t.loc[i].addr; | 2925 | struct location *l = &t.loc[i]; |
2892 | 2926 | ||
2893 | if (n > PAGE_SIZE - 100) | 2927 | if (n > PAGE_SIZE - 100) |
2894 | break; | 2928 | break; |
2895 | n += sprintf(buf + n, "%7ld ", t.loc[i].count); | 2929 | n += sprintf(buf + n, "%7ld ", l->count); |
2896 | if (addr) | 2930 | |
2897 | n += sprint_symbol(buf + n, (unsigned long)t.loc[i].addr); | 2931 | if (l->addr) |
2932 | n += sprint_symbol(buf + n, (unsigned long)l->addr); | ||
2898 | else | 2933 | else |
2899 | n += sprintf(buf + n, "<not-available>"); | 2934 | n += sprintf(buf + n, "<not-available>"); |
2935 | |||
2936 | if (l->sum_time != l->min_time) { | ||
2937 | unsigned long remainder; | ||
2938 | |||
2939 | n += sprintf(buf + n, " age=%ld/%ld/%ld", | ||
2940 | l->min_time, | ||
2941 | div_long_long_rem(l->sum_time, l->count, &remainder), | ||
2942 | l->max_time); | ||
2943 | } else | ||
2944 | n += sprintf(buf + n, " age=%ld", | ||
2945 | l->min_time); | ||
2946 | |||
2947 | if (l->min_pid != l->max_pid) | ||
2948 | n += sprintf(buf + n, " pid=%ld-%ld", | ||
2949 | l->min_pid, l->max_pid); | ||
2950 | else | ||
2951 | n += sprintf(buf + n, " pid=%ld", | ||
2952 | l->min_pid); | ||
2953 | |||
2954 | if (num_online_cpus() > 1 && !cpus_empty(l->cpus)) { | ||
2955 | n += sprintf(buf + n, " cpus="); | ||
2956 | n += cpulist_scnprintf(buf + n, PAGE_SIZE - n - 50, | ||
2957 | l->cpus); | ||
2958 | } | ||
2959 | |||
2960 | if (num_online_nodes() > 1 && !nodes_empty(l->nodes)) { | ||
2961 | n += sprintf(buf + n, " nodes="); | ||
2962 | n += nodelist_scnprintf(buf + n, PAGE_SIZE - n - 50, | ||
2963 | l->nodes); | ||
2964 | } | ||
2965 | |||
2900 | n += sprintf(buf + n, "\n"); | 2966 | n += sprintf(buf + n, "\n"); |
2901 | } | 2967 | } |
2902 | 2968 | ||