| @@ -19,6 +19,13 @@ · 18 unmodified lines |
| 19 | * for anonymous memory. For process policy an process counter | 19 | * for anonymous memory. For process policy an process counter |
| 20 | * is used. | 20 | * is used. |
| 21 | * | 21 | * |
| | 22 | * weighted interleave |
| | 23 | * Allocate memory interleaved over a set of nodes based on |
| | 24 | * a set of weights (per-node), with normal fallback if it |
| | 25 | * fails. Otherwise operates the same as interleave. |
| | 26 | * Example: nodeset(0,1) & weights (2,1) - 2 pages allocated |
| | 27 | * on node 0 for every 1 page allocated on node 1. |
| | 28 | * |
| 22 | * bind Only allocate memory on a specific set of nodes, | 29 | * bind Only allocate memory on a specific set of nodes, |
| 23 | * no fallback. | 30 | * no fallback. |
| 24 | * FIXME: memory is allocated starting with the first node | 31 | * FIXME: memory is allocated starting with the first node |
| @@ -441,6 +448,10 @@ static const struct mempolicy_operations mpol_ops[MPOL_MAX] = { · 416 unmodified lines |
| 441 | .create = mpol_new_nodemask, | 448 | .create = mpol_new_nodemask, |
| 442 | .rebind = mpol_rebind_preferred, | 449 | .rebind = mpol_rebind_preferred, |
| 443 | }, | 450 | }, |
| | 451 | [MPOL_WEIGHTED_INTERLEAVE] = { |
| | 452 | .create = mpol_new_nodemask, |
| | 453 | .rebind = mpol_rebind_nodemask, |
| | 454 | }, |
| 444 | }; | 455 | }; |
| 445 | | 456 | |
| 446 | static bool migrate_folio_add(struct folio *folio, struct list_head *foliolist, | 457 | static bool migrate_folio_add(struct folio *folio, struct list_head *foliolist, |
| @@ -858,8 +869,11 @@ static long do_set_mempolicy(unsigned short mode, unsigned short flags, · 411 unmodified lines |
| 858 | | 869 | |
| 859 | old = current->mempolicy; | 870 | old = current->mempolicy; |
| 860 | current->mempolicy = new; | 871 | current->mempolicy = new; |
| 861 | if (new && new->mode == MPOL_INTERLEAVE) | 872 | if (new && (new->mode == MPOL_INTERLEAVE || |
| | 873 | new->mode == MPOL_WEIGHTED_INTERLEAVE)) { |
| 862 | current->il_prev = MAX_NUMNODES-1; | 874 | current->il_prev = MAX_NUMNODES-1; |
| | 875 | current->il_weight = 0; |
| | 876 | } |
| 863 | task_unlock(current); | 877 | task_unlock(current); |
| 864 | mpol_put(old); | 878 | mpol_put(old); |
| 865 | ret = 0; | 879 | ret = 0; |
| @@ -884,6 +898,7 @@ static void get_policy_nodemask(struct mempolicy *pol, nodemask_t *nodes) · 18 unmodified lines |
| 884 | case MPOL_INTERLEAVE: | 898 | case MPOL_INTERLEAVE: |
| 885 | case MPOL_PREFERRED: | 899 | case MPOL_PREFERRED: |
| 886 | case MPOL_PREFERRED_MANY: | 900 | case MPOL_PREFERRED_MANY: |
| | 901 | case MPOL_WEIGHTED_INTERLEAVE: |
| 887 | *nodes = pol->nodes; | 902 | *nodes = pol->nodes; |
| 888 | break; | 903 | break; |
| 889 | case MPOL_LOCAL: | 904 | case MPOL_LOCAL: |
| @@ -968,6 +983,13 @@ static long do_get_mempolicy(int *policy, nodemask_t *nmask, · 78 unmodified lines |
| 968 | } else if (pol == current->mempolicy && | 983 | } else if (pol == current->mempolicy && |
| 969 | pol->mode == MPOL_INTERLEAVE) { | 984 | pol->mode == MPOL_INTERLEAVE) { |
| 970 | *policy = next_node_in(current->il_prev, pol->nodes); | 985 | *policy = next_node_in(current->il_prev, pol->nodes); |
| | 986 | } else if (pol == current->mempolicy && |
| | 987 | pol->mode == MPOL_WEIGHTED_INTERLEAVE) { |
| | 988 | if (current->il_weight) |
| | 989 | *policy = current->il_prev; |
| | 990 | else |
| | 991 | *policy = next_node_in(current->il_prev, |
| | 992 | pol->nodes); |
| 971 | } else { | 993 | } else { |
| 972 | err = -EINVAL; | 994 | err = -EINVAL; |
| 973 | goto out; | 995 | goto out; |
| @@ -1332,7 +1354,8 @@ static long do_mbind(unsigned long start, unsigned long len, · 358 unmodified lines |
| 1332 | * VMAs, the nodes will still be interleaved from the targeted | 1354 | * VMAs, the nodes will still be interleaved from the targeted |
| 1333 | * nodemask, but one by one may be selected differently. | 1355 | * nodemask, but one by one may be selected differently. |
| 1334 | */ | 1356 | */ |
| 1335 | if (new->mode == MPOL_INTERLEAVE) { | 1357 | if (new->mode == MPOL_INTERLEAVE || |
| | 1358 | new->mode == MPOL_WEIGHTED_INTERLEAVE) { |
| 1336 | struct page *page; | 1359 | struct page *page; |
| 1337 | unsigned int order; | 1360 | unsigned int order; |
| 1338 | unsigned long addr = -EFAULT; | 1361 | unsigned long addr = -EFAULT; |
| @@ -1780,7 +1803,8 @@ struct mempolicy *__get_vma_policy(struct vm_area_struct *vma, · 441 unmodified lines |
| 1780 | * @vma: virtual memory area whose policy is sought | 1803 | * @vma: virtual memory area whose policy is sought |
| 1781 | * @addr: address in @vma for shared policy lookup | 1804 | * @addr: address in @vma for shared policy lookup |
| 1782 | * @order: 0, or appropriate huge_page_order for interleaving | 1805 | * @order: 0, or appropriate huge_page_order for interleaving |
| 1783 | * @ilx: interleave index (output), for use only when MPOL_INTERLEAVE | 1806 | * @ilx: interleave index (output), for use only when MPOL_INTERLEAVE or |
| | 1807 | * MPOL_WEIGHTED_INTERLEAVE |
| 1784 | * | 1808 | * |
| 1785 | * Returns effective policy for a VMA at specified address. | 1809 | * Returns effective policy for a VMA at specified address. |
| 1786 | * Falls back to current->mempolicy or system default policy, as necessary. | 1810 | * Falls back to current->mempolicy or system default policy, as necessary. |
| @@ -1797,7 +1821,8 @@ struct mempolicy *get_vma_policy(struct vm_area_struct *vma, · 10 unmodified lines |
| 1797 | pol = __get_vma_policy(vma, addr, ilx); | 1821 | pol = __get_vma_policy(vma, addr, ilx); |
| 1798 | if (!pol) | 1822 | if (!pol) |
| 1799 | pol = get_task_policy(current); | 1823 | pol = get_task_policy(current); |
| 1800 | if (pol->mode == MPOL_INTERLEAVE) { | 1824 | if (pol->mode == MPOL_INTERLEAVE || |
| | 1825 | pol->mode == MPOL_WEIGHTED_INTERLEAVE) { |
| 1801 | *ilx += vma->vm_pgoff >> order; | 1826 | *ilx += vma->vm_pgoff >> order; |
| 1802 | *ilx += (addr - vma->vm_start) >> (PAGE_SHIFT + order); | 1827 | *ilx += (addr - vma->vm_start) >> (PAGE_SHIFT + order); |
| 1803 | } | 1828 | } |
| @@ -1847,6 +1872,22 @@ bool apply_policy_zone(struct mempolicy *policy, enum zone_type zone) · 43 unmodified lines |
| 1847 | return zone >= dynamic_policy_zone; | 1872 | return zone >= dynamic_policy_zone; |
| 1848 | } | 1873 | } |
| 1849 | | 1874 | |
| | 1875 | static unsigned int weighted_interleave_nodes(struct mempolicy *policy) |
| | 1876 | { |
| | 1877 | unsigned int node = current->il_prev; |
| | 1878 | |
| | 1879 | if (!current->il_weight || !node_isset(node, policy->nodes)) { |
| | 1880 | node = next_node_in(node, policy->nodes); |
| | 1881 | /* can only happen if nodemask is being rebound */ |
| | 1882 | if (node == MAX_NUMNODES) |
| | 1883 | return node; |
| | 1884 | current->il_prev = node; |
| | 1885 | current->il_weight = get_il_weight(node); |
| | 1886 | } |
| | 1887 | current->il_weight--; |
| | 1888 | return node; |
| | 1889 | } |
| | 1890 | |
| 1850 | /* Do dynamic interleaving for a process */ | 1891 | /* Do dynamic interleaving for a process */ |
| 1851 | static unsigned int interleave_nodes(struct mempolicy *policy) | 1892 | static unsigned int interleave_nodes(struct mempolicy *policy) |
| 1852 | { | 1893 | { |
| @@ -1881,6 +1922,9 @@ unsigned int mempolicy_slab_node(void) · 28 unmodified lines |
| 1881 | case MPOL_INTERLEAVE: | 1922 | case MPOL_INTERLEAVE: |
| 1882 | return interleave_nodes(policy); | 1923 | return interleave_nodes(policy); |
| 1883 | | 1924 | |
| | 1925 | case MPOL_WEIGHTED_INTERLEAVE: |
| | 1926 | return weighted_interleave_nodes(policy); |
| | 1927 | |
| 1884 | case MPOL_BIND: | 1928 | case MPOL_BIND: |
| 1885 | case MPOL_PREFERRED_MANY: | 1929 | case MPOL_PREFERRED_MANY: |
| 1886 | { | 1930 | { |
| @@ -1919,6 +1963,45 @@ static unsigned int read_once_policy_nodemask(struct mempolicy *pol, · 32 unmodified lines |
| 1919 | return nodes_weight(*mask); | 1963 | return nodes_weight(*mask); |
| 1920 | } | 1964 | } |
| 1921 | | 1965 | |
| | 1966 | static unsigned int weighted_interleave_nid(struct mempolicy *pol, pgoff_t ilx) |
| | 1967 | { |
| | 1968 | nodemask_t nodemask; |
| | 1969 | unsigned int target, nr_nodes; |
| | 1970 | u8 *table; |
| | 1971 | unsigned int weight_total = 0; |
| | 1972 | u8 weight; |
| | 1973 | int nid; |
| | 1974 | |
| | 1975 | nr_nodes = read_once_policy_nodemask(pol, &nodemask); |
| | 1976 | if (!nr_nodes) |
| | 1977 | return numa_node_id(); |
| | 1978 | |
| | 1979 | rcu_read_lock(); |
| | 1980 | table = rcu_dereference(iw_table); |
| | 1981 | /* calculate the total weight */ |
| | 1982 | for_each_node_mask(nid, nodemask) { |
| | 1983 | /* detect system default usage */ |
| | 1984 | weight = table ? table[nid] : 1; |
| | 1985 | weight = weight ? weight : 1; |
| | 1986 | weight_total += weight; |
| | 1987 | } |
| | 1988 | |
| | 1989 | /* Calculate the node offset based on totals */ |
| | 1990 | target = ilx % weight_total; |
| | 1991 | nid = first_node(nodemask); |
| | 1992 | while (target) { |
| | 1993 | /* detect system default usage */ |
| | 1994 | weight = table ? table[nid] : 1; |
| | 1995 | weight = weight ? weight : 1; |
| | 1996 | if (target < weight) |
| | 1997 | break; |
| | 1998 | target -= weight; |
| | 1999 | nid = next_node_in(nid, nodemask); |
| | 2000 | } |
| | 2001 | rcu_read_unlock(); |
| | 2002 | return nid; |
| | 2003 | } |
| | 2004 | |
| 1922 | /* | 2005 | /* |
| 1923 | * Do static interleaving for interleave index @ilx. Returns the ilx'th | 2006 | * Do static interleaving for interleave index @ilx. Returns the ilx'th |
| 1924 | * node in pol->nodes (starting from ilx=0), wrapping around if ilx | 2007 | * node in pol->nodes (starting from ilx=0), wrapping around if ilx |
| @@ -1979,6 +2062,11 @@ static nodemask_t *policy_nodemask(gfp_t gfp, struct mempolicy *pol, · 54 unmodified lines |
| 1979 | *nid = (ilx == NO_INTERLEAVE_INDEX) ? | 2062 | *nid = (ilx == NO_INTERLEAVE_INDEX) ? |
| 1980 | interleave_nodes(pol) : interleave_nid(pol, ilx); | 2063 | interleave_nodes(pol) : interleave_nid(pol, ilx); |
| 1981 | break; | 2064 | break; |
| | 2065 | case MPOL_WEIGHTED_INTERLEAVE: |
| | 2066 | *nid = (ilx == NO_INTERLEAVE_INDEX) ? |
| | 2067 | weighted_interleave_nodes(pol) : |
| | 2068 | weighted_interleave_nid(pol, ilx); |
| | 2069 | break; |
| 1982 | } | 2070 | } |
| 1983 | | 2071 | |
| 1984 | return nodemask; | 2072 | return nodemask; |
| @@ -2040,6 +2128,7 @@ bool init_nodemask_of_mempolicy(nodemask_t *mask) · 55 unmodified lines |
| 2040 | case MPOL_PREFERRED_MANY: | 2128 | case MPOL_PREFERRED_MANY: |
| 2041 | case MPOL_BIND: | 2129 | case MPOL_BIND: |
| 2042 | case MPOL_INTERLEAVE: | 2130 | case MPOL_INTERLEAVE: |
| | 2131 | case MPOL_WEIGHTED_INTERLEAVE: |
| 2043 | *mask = mempolicy->nodes; | 2132 | *mask = mempolicy->nodes; |
| 2044 | break; | 2133 | break; |
| 2045 | | 2134 | |
| @@ -2140,6 +2229,7 @@ struct page *alloc_pages_mpol(gfp_t gfp, unsigned int order, · 94 unmodified lines |
| 2140 | * node in its nodemask, we allocate the standard way. | 2229 | * node in its nodemask, we allocate the standard way. |
| 2141 | */ | 2230 | */ |
| 2142 | if (pol->mode != MPOL_INTERLEAVE && | 2231 | if (pol->mode != MPOL_INTERLEAVE && |
| | 2232 | pol->mode != MPOL_WEIGHTED_INTERLEAVE && |
| 2143 | (!nodemask || node_isset(nid, *nodemask))) { | 2233 | (!nodemask || node_isset(nid, *nodemask))) { |
| 2144 | /* | 2234 | /* |
| 2145 | * First, try to allocate THP only on local node, but | 2235 | * First, try to allocate THP only on local node, but |
| @@ -2275,6 +2365,114 @@ static unsigned long alloc_pages_bulk_array_interleave(gfp_t gfp, · 129 unmodified lines |
| 2275 | return total_allocated; | 2365 | return total_allocated; |
| 2276 | } | 2366 | } |
| 2277 | | 2367 | |
| | 2368 | static unsigned long alloc_pages_bulk_array_weighted_interleave(gfp_t gfp, |
| | 2369 | struct mempolicy *pol, unsigned long nr_pages, |
| | 2370 | struct page **page_array) |
| | 2371 | { |
| | 2372 | struct task_struct *me = current; |
| | 2373 | unsigned long total_allocated = 0; |
| | 2374 | unsigned long nr_allocated = 0; |
| | 2375 | unsigned long rounds; |
| | 2376 | unsigned long node_pages, delta; |
| | 2377 | u8 *table, *weights, weight; |
| | 2378 | unsigned int weight_total = 0; |
| | 2379 | unsigned long rem_pages = nr_pages; |
| | 2380 | nodemask_t nodes; |
| | 2381 | int nnodes, node; |
| | 2382 | int resume_node = MAX_NUMNODES - 1; |
| | 2383 | u8 resume_weight = 0; |
| | 2384 | int prev_node; |
| | 2385 | int i; |
| | 2386 | |
| | 2387 | if (!nr_pages) |
| | 2388 | return 0; |
| | 2389 | |
| | 2390 | nnodes = read_once_policy_nodemask(pol, &nodes); |
| | 2391 | if (!nnodes) |
| | 2392 | return 0; |
| | 2393 | |
| | 2394 | /* Continue allocating from most recent node and adjust the nr_pages */ |
| | 2395 | node = me->il_prev; |
| | 2396 | weight = me->il_weight; |
| | 2397 | if (weight && node_isset(node, nodes)) { |
| | 2398 | node_pages = min(rem_pages, weight); |
| | 2399 | nr_allocated = __alloc_pages_bulk(gfp, node, NULL, node_pages, |
| | 2400 | NULL, page_array); |
| | 2401 | page_array += nr_allocated; |
| | 2402 | total_allocated += nr_allocated; |
| | 2403 | /* if that's all the pages, no need to interleave */ |
| | 2404 | if (rem_pages <= weight) { |
| | 2405 | me->il_weight -= rem_pages; |
| | 2406 | return total_allocated; |
| | 2407 | } |
| | 2408 | /* Otherwise we adjust remaining pages, continue from there */ |
| | 2409 | rem_pages -= weight; |
| | 2410 | } |
| | 2411 | /* clear active weight in case of an allocation failure */ |
| | 2412 | me->il_weight = 0; |
| | 2413 | prev_node = node; |
| | 2414 | |
| | 2415 | /* create a local copy of node weights to operate on outside rcu */ |
| | 2416 | weights = kzalloc(nr_node_ids, GFP_KERNEL); |
| | 2417 | if (!weights) |
| | 2418 | return total_allocated; |
| | 2419 | |
| | 2420 | rcu_read_lock(); |
| | 2421 | table = rcu_dereference(iw_table); |
| | 2422 | if (table) |
| | 2423 | memcpy(weights, table, nr_node_ids); |
| | 2424 | rcu_read_unlock(); |
| | 2425 | |
| | 2426 | /* calculate total, detect system default usage */ |
| | 2427 | for_each_node_mask(node, nodes) { |
| | 2428 | if (!weights[node]) |
| | 2429 | weights[node] = 1; |
| | 2430 | weight_total += weights[node]; |
| | 2431 | } |
| | 2432 | |
| | 2433 | /* |
| | 2434 | * Calculate rounds/partial rounds to minimize __alloc_pages_bulk calls. |
| | 2435 | * Track which node weighted interleave should resume from. |
| | 2436 | * |
| | 2437 | * if (rounds > 0) and (delta == 0), resume_node will always be |
| | 2438 | * the node following prev_node and its weight. |
| | 2439 | */ |
| | 2440 | rounds = rem_pages / weight_total; |
| | 2441 | delta = rem_pages % weight_total; |
| | 2442 | resume_node = next_node_in(prev_node, nodes); |
| | 2443 | resume_weight = weights[resume_node]; |
| | 2444 | for (i = 0; i < nnodes; i++) { |
| | 2445 | node = next_node_in(prev_node, nodes); |
| | 2446 | weight = weights[node]; |
| | 2447 | node_pages = weight * rounds; |
| | 2448 | /* If a delta exists, add this node's portion of the delta */ |
| | 2449 | if (delta > weight) { |
| | 2450 | node_pages += weight; |
| | 2451 | delta -= weight; |
| | 2452 | } else if (delta) { |
| | 2453 | /* when delta is depleted, resume from that node */ |
| | 2454 | node_pages += delta; |
| | 2455 | resume_node = node; |
| | 2456 | resume_weight = weight - delta; |
| | 2457 | delta = 0; |
| | 2458 | } |
| | 2459 | /* node_pages can be 0 if an allocation fails and rounds == 0 */ |
| | 2460 | if (!node_pages) |
| | 2461 | break; |
| | 2462 | nr_allocated = __alloc_pages_bulk(gfp, node, NULL, node_pages, |
| | 2463 | NULL, page_array); |
| | 2464 | page_array += nr_allocated; |
| | 2465 | total_allocated += nr_allocated; |
| | 2466 | if (total_allocated == nr_pages) |
| | 2467 | break; |
| | 2468 | prev_node = node; |
| | 2469 | } |
| | 2470 | me->il_prev = resume_node; |
| | 2471 | me->il_weight = resume_weight; |
| | 2472 | kfree(weights); |
| | 2473 | return total_allocated; |
| | 2474 | } |
| | 2475 | |
| 2278 | static unsigned long alloc_pages_bulk_array_preferred_many(gfp_t gfp, int nid, | 2476 | static unsigned long alloc_pages_bulk_array_preferred_many(gfp_t gfp, int nid, |
| 2279 | struct mempolicy *pol, unsigned long nr_pages, | 2477 | struct mempolicy *pol, unsigned long nr_pages, |
| 2280 | struct page **page_array) | 2478 | struct page **page_array) |
| @@ -2315,6 +2513,10 @@ unsigned long alloc_pages_bulk_array_mempolicy(gfp_t gfp, · 34 unmodified lines |
| 2315 | return alloc_pages_bulk_array_interleave(gfp, pol, | 2513 | return alloc_pages_bulk_array_interleave(gfp, pol, |
| 2316 | nr_pages, page_array); | 2514 | nr_pages, page_array); |
| 2317 | | 2515 | |
| | 2516 | if (pol->mode == MPOL_WEIGHTED_INTERLEAVE) |
| | 2517 | return alloc_pages_bulk_array_weighted_interleave( |
| | 2518 | gfp, pol, nr_pages, page_array); |
| | 2519 | |
| 2318 | if (pol->mode == MPOL_PREFERRED_MANY) | 2520 | if (pol->mode == MPOL_PREFERRED_MANY) |
| 2319 | return alloc_pages_bulk_array_preferred_many(gfp, | 2521 | return alloc_pages_bulk_array_preferred_many(gfp, |
| 2320 | numa_node_id(), pol, nr_pages, page_array); | 2522 | numa_node_id(), pol, nr_pages, page_array); |
| @@ -2390,6 +2592,7 @@ bool __mpol_equal(struct mempolicy *a, struct mempolicy *b) · 69 unmodified lines |
| 2390 | case MPOL_INTERLEAVE: | 2592 | case MPOL_INTERLEAVE: |
| 2391 | case MPOL_PREFERRED: | 2593 | case MPOL_PREFERRED: |
| 2392 | case MPOL_PREFERRED_MANY: | 2594 | case MPOL_PREFERRED_MANY: |
| | 2595 | case MPOL_WEIGHTED_INTERLEAVE: |
| 2393 | return !!nodes_equal(a->nodes, b->nodes); | 2596 | return !!nodes_equal(a->nodes, b->nodes); |
| 2394 | case MPOL_LOCAL: | 2597 | case MPOL_LOCAL: |
| 2395 | return true; | 2598 | return true; |
| @@ -2526,6 +2729,10 @@ int mpol_misplaced(struct folio *folio, struct vm_area_struct *vma, · 130 unmodified lines |
| 2526 | polnid = interleave_nid(pol, ilx); | 2729 | polnid = interleave_nid(pol, ilx); |
| 2527 | break; | 2730 | break; |
| 2528 | | 2731 | |
| | 2732 | case MPOL_WEIGHTED_INTERLEAVE: |
| | 2733 | polnid = weighted_interleave_nid(pol, ilx); |
| | 2734 | break; |
| | 2735 | |
| 2529 | case MPOL_PREFERRED: | 2736 | case MPOL_PREFERRED: |
| 2530 | if (node_isset(curnid, pol->nodes)) | 2737 | if (node_isset(curnid, pol->nodes)) |
| 2531 | goto out; | 2738 | goto out; |
| @@ -2900,6 +3107,7 @@ static const char * const policy_modes[] = · 368 unmodified lines |
| 2900 | [MPOL_PREFERRED] = "prefer", | 3107 | [MPOL_PREFERRED] = "prefer", |
| 2901 | [MPOL_BIND] = "bind", | 3108 | [MPOL_BIND] = "bind", |
| 2902 | [MPOL_INTERLEAVE] = "interleave", | 3109 | [MPOL_INTERLEAVE] = "interleave", |
| | 3110 | [MPOL_WEIGHTED_INTERLEAVE] = "weighted interleave", |
| 2903 | [MPOL_LOCAL] = "local", | 3111 | [MPOL_LOCAL] = "local", |
| 2904 | [MPOL_PREFERRED_MANY] = "prefer (many)", | 3112 | [MPOL_PREFERRED_MANY] = "prefer (many)", |
| 2905 | }; | 3113 | }; |
| @@ -2959,6 +3167,7 @@ int mpol_parse_str(char *str, struct mempolicy **mpol) · 53 unmodified lines |
| 2959 | } | 3167 | } |
| 2960 | break; | 3168 | break; |
| 2961 | case MPOL_INTERLEAVE: | 3169 | case MPOL_INTERLEAVE: |
| | 3170 | case MPOL_WEIGHTED_INTERLEAVE: |
| 2962 | /* | 3171 | /* |
| 2963 | * Default to online nodes with memory if no nodelist | 3172 | * Default to online nodes with memory if no nodelist |
| 2964 | */ | 3173 | */ |
| @@ -3069,6 +3278,7 @@ void mpol_to_str(char *buffer, int maxlen, struct mempolicy *pol) · 104 unmodified lines |
| 3069 | case MPOL_PREFERRED_MANY: | 3278 | case MPOL_PREFERRED_MANY: |
| 3070 | case MPOL_BIND: | 3279 | case MPOL_BIND: |
| 3071 | case MPOL_INTERLEAVE: | 3280 | case MPOL_INTERLEAVE: |
| | 3281 | case MPOL_WEIGHTED_INTERLEAVE: |
| 3072 | nodes = pol->nodes; | 3282 | nodes = pol->nodes; |
| 3073 | break; | 3283 | break; |
| 3074 | default: | 3284 | default: |