Merge misc fixes from Andrew Morton: "16 fixes" * emailed patches from Andrew Morton <akpm@linux-foundation.org>: mm/devm_memremap_pages: fix final page put race PCI/P2PDMA: track pgmap references per resource, not globally lib/genalloc: introduce chunk owners PCI/P2PDMA: fix the gen_pool_add_virt() failure path mm/devm_memremap_pages: introduce devm_memunmap_pages drivers/base/devres: introduce devm_release_action() mm/vmscan.c: fix trying to reclaim unevictable LRU page coredump: fix race condition between collapse_huge_page() and core dumping mm/mlock.c: change count_mm_mlocked_page_nr return type mm: mmu_gather: remove __tlb_reset_range() for force flush fs/ocfs2: fix race in ocfs2_dentry_attach_lock() mm/vmscan.c: fix recent_rotated history mm/mlock.c: mlockall error for flag MCL_ONFAULT scripts/decode_stacktrace.sh: prefix addr2line with $CROSS_COMPILE mm/list_lru.c: fix memory leak in __memcg_init_list_lru_node mm: memcontrol: don't batch updates of local VM stats and events
Unified · Split
| @@ -755,10 +755,32 @@ void devm_remove_action(struct device *dev, void (*action)(void *), void *data) · 754 unmodified lines | |||
| 755 | 755 | ||
| 756 | WARN_ON(devres_destroy(dev, devm_action_release, devm_action_match, | 756 | WARN_ON(devres_destroy(dev, devm_action_release, devm_action_match, |
| 757 | &devres)); | 757 | &devres)); |
| 758 | |||
| 759 | } | 758 | } |
| 760 | EXPORT_SYMBOL_GPL(devm_remove_action); | 759 | EXPORT_SYMBOL_GPL(devm_remove_action); |
| 761 | 760 | ||
| 761 | /** | ||
| 762 | * devm_release_action() - release previously added custom action | ||
| 763 | * @dev: Device that owns the action | ||
| 764 | * @action: Function implementing the action | ||
| 765 | * @data: Pointer to data passed to @action implementation | ||
| 766 | * | ||
| 767 | * Releases and removes instance of @action previously added by | ||
| 768 | * devm_add_action(). Both action and data should match one of the | ||
| 769 | * existing entries. | ||
| 770 | */ | ||
| 771 | void devm_release_action(struct device *dev, void (*action)(void *), void *data) | ||
| 772 | { | ||
| 773 | struct action_devres devres = { | ||
| 774 | .data = data, | ||
| 775 | .action = action, | ||
| 776 | }; | ||
| 777 | |||
| 778 | WARN_ON(devres_release(dev, devm_action_release, devm_action_match, | ||
| 779 | &devres)); | ||
| 780 | |||
| 781 | } | ||
| 782 | EXPORT_SYMBOL_GPL(devm_release_action); | ||
| 783 | |||
| 762 | /* | 784 | /* |
| 763 | * Managed kmalloc/kfree | 785 | * Managed kmalloc/kfree |
| 764 | */ | 786 | */ |
| @@ -27,9 +27,8 @@ static void dev_dax_percpu_release(struct percpu_ref *ref) · 26 unmodified lines | |||
| 27 | complete(&dev_dax->cmp); | 27 | complete(&dev_dax->cmp); |
| 28 | } | 28 | } |
| 29 | 29 | ||
| 30 | static void dev_dax_percpu_exit(void *data) | 30 | static void dev_dax_percpu_exit(struct percpu_ref *ref) |
| 31 | { | 31 | { |
| 32 | struct percpu_ref *ref = data; | ||
| 33 | struct dev_dax *dev_dax = ref_to_dev_dax(ref); | 32 | struct dev_dax *dev_dax = ref_to_dev_dax(ref); |
| 34 | 33 | ||
| 35 | dev_dbg(&dev_dax->dev, "%s\n", __func__); | 34 | dev_dbg(&dev_dax->dev, "%s\n", __func__); |
| @@ -466,18 +465,12 @@ int dev_dax_probe(struct device *dev) · 430 unmodified lines | |||
| 466 | if (rc) | 465 | if (rc) |
| 467 | return rc; | 466 | return rc; |
| 468 | 467 | ||
| 469 | rc = devm_add_action_or_reset(dev, dev_dax_percpu_exit, &dev_dax->ref); | ||
| 470 | if (rc) | ||
| 471 | return rc; | ||
| 472 | |||
| 473 | dev_dax->pgmap.ref = &dev_dax->ref; | 468 | dev_dax->pgmap.ref = &dev_dax->ref; |
| 474 | dev_dax->pgmap.kill = dev_dax_percpu_kill; | 469 | dev_dax->pgmap.kill = dev_dax_percpu_kill; |
| 470 | dev_dax->pgmap.cleanup = dev_dax_percpu_exit; | ||
| 475 | addr = devm_memremap_pages(dev, &dev_dax->pgmap); | 471 | addr = devm_memremap_pages(dev, &dev_dax->pgmap); |
| 476 | if (IS_ERR(addr)) { | 472 | if (IS_ERR(addr)) |
| 477 | devm_remove_action(dev, dev_dax_percpu_exit, &dev_dax->ref); | ||
| 478 | percpu_ref_exit(&dev_dax->ref); | ||
| 479 | return PTR_ERR(addr); | 473 | return PTR_ERR(addr); |
| 480 | } | ||
| 481 | 474 | ||
| 482 | inode = dax_inode(dax_dev); | 475 | inode = dax_inode(dax_dev); |
| 483 | cdev = inode->i_cdev; | 476 | cdev = inode->i_cdev; |
| @@ -303,11 +303,19 @@ static const struct attribute_group *pmem_attribute_groups[] = { · 302 unmodified lines | |||
| 303 | NULL, | 303 | NULL, |
| 304 | }; | 304 | }; |
| 305 | 305 | ||
| 306 | static void pmem_release_queue(void *q) | 306 | static void __pmem_release_queue(struct percpu_ref *ref) |
| 307 | { | 307 | { |
| 308 | struct request_queue *q; | ||
| 309 | |||
| 310 | q = container_of(ref, typeof(*q), q_usage_counter); | ||
| 308 | blk_cleanup_queue(q); | 311 | blk_cleanup_queue(q); |
| 309 | } | 312 | } |
| 310 | 313 | ||
| 314 | static void pmem_release_queue(void *ref) | ||
| 315 | { | ||
| 316 | __pmem_release_queue(ref); | ||
| 317 | } | ||
| 318 | |||
| 311 | static void pmem_freeze_queue(struct percpu_ref *ref) | 319 | static void pmem_freeze_queue(struct percpu_ref *ref) |
| 312 | { | 320 | { |
| 313 | struct request_queue *q; | 321 | struct request_queue *q; |
| @@ -399,12 +407,10 @@ static int pmem_attach_disk(struct device *dev, · 85 unmodified lines | |||
| 399 | if (!q) | 407 | if (!q) |
| 400 | return -ENOMEM; | 408 | return -ENOMEM; |
| 401 | 409 | ||
| 402 | if (devm_add_action_or_reset(dev, pmem_release_queue, q)) | ||
| 403 | return -ENOMEM; | ||
| 404 | |||
| 405 | pmem->pfn_flags = PFN_DEV; | 410 | pmem->pfn_flags = PFN_DEV; |
| 406 | pmem->pgmap.ref = &q->q_usage_counter; | 411 | pmem->pgmap.ref = &q->q_usage_counter; |
| 407 | pmem->pgmap.kill = pmem_freeze_queue; | 412 | pmem->pgmap.kill = pmem_freeze_queue; |
| 413 | pmem->pgmap.cleanup = __pmem_release_queue; | ||
| 408 | if (is_nd_pfn(dev)) { | 414 | if (is_nd_pfn(dev)) { |
| 409 | if (setup_pagemap_fsdax(dev, &pmem->pgmap)) | 415 | if (setup_pagemap_fsdax(dev, &pmem->pgmap)) |
| 410 | return -ENOMEM; | 416 | return -ENOMEM; |
| @@ -425,6 +431,9 @@ static int pmem_attach_disk(struct device *dev, · 14 unmodified lines | |||
| 425 | pmem->pfn_flags |= PFN_MAP; | 431 | pmem->pfn_flags |= PFN_MAP; |
| 426 | memcpy(&bb_res, &pmem->pgmap.res, sizeof(bb_res)); | 432 | memcpy(&bb_res, &pmem->pgmap.res, sizeof(bb_res)); |
| 427 | } else { | 433 | } else { |
| 434 | if (devm_add_action_or_reset(dev, pmem_release_queue, | ||
| 435 | &q->q_usage_counter)) | ||
| 436 | return -ENOMEM; | ||
| 428 | addr = devm_memremap(dev, pmem->phys_addr, | 437 | addr = devm_memremap(dev, pmem->phys_addr, |
| 429 | pmem->size, ARCH_MEMREMAP_PMEM); | 438 | pmem->size, ARCH_MEMREMAP_PMEM); |
| 430 | memcpy(&bb_res, &nsio->res, sizeof(bb_res)); | 439 | memcpy(&bb_res, &nsio->res, sizeof(bb_res)); |
| @@ -20,12 +20,16 @@ · 19 unmodified lines | |||
| 20 | #include <linux/seq_buf.h> | 20 | #include <linux/seq_buf.h> |
| 21 | 21 | ||
| 22 | struct pci_p2pdma { | 22 | struct pci_p2pdma { |
| 23 | struct percpu_ref devmap_ref; | ||
| 24 | struct completion devmap_ref_done; | ||
| 25 | struct gen_pool *pool; | 23 | struct gen_pool *pool; |
| 26 | bool p2pmem_published; | 24 | bool p2pmem_published; |
| 27 | }; | 25 | }; |
| 28 | 26 | ||
| 27 | struct p2pdma_pagemap { | ||
| 28 | struct dev_pagemap pgmap; | ||
| 29 | struct percpu_ref ref; | ||
| 30 | struct completion ref_done; | ||
| 31 | }; | ||
| 32 | |||
| 29 | static ssize_t size_show(struct device *dev, struct device_attribute *attr, | 33 | static ssize_t size_show(struct device *dev, struct device_attribute *attr, |
| 30 | char *buf) | 34 | char *buf) |
| 31 | { | 35 | { |
| @@ -74,41 +78,45 @@ static const struct attribute_group p2pmem_group = { · 42 unmodified lines | |||
| 74 | .name = "p2pmem", | 78 | .name = "p2pmem", |
| 75 | }; | 79 | }; |
| 76 | 80 | ||
| 81 | static struct p2pdma_pagemap *to_p2p_pgmap(struct percpu_ref *ref) | ||
| 82 | { | ||
| 83 | return container_of(ref, struct p2pdma_pagemap, ref); | ||
| 84 | } | ||
| 85 | |||
| 77 | static void pci_p2pdma_percpu_release(struct percpu_ref *ref) | 86 | static void pci_p2pdma_percpu_release(struct percpu_ref *ref) |
| 78 | { | 87 | { |
| 79 | struct pci_p2pdma *p2p = | 88 | struct p2pdma_pagemap *p2p_pgmap = to_p2p_pgmap(ref); |
| 80 | container_of(ref, struct pci_p2pdma, devmap_ref); | ||
| 81 | 89 | ||
| 82 | complete_all(&p2p->devmap_ref_done); | 90 | complete(&p2p_pgmap->ref_done); |
| 83 | } | 91 | } |
| 84 | 92 | ||
| 85 | static void pci_p2pdma_percpu_kill(struct percpu_ref *ref) | 93 | static void pci_p2pdma_percpu_kill(struct percpu_ref *ref) |
| 86 | { | 94 | { |
| 87 | /* | ||
| 88 | * pci_p2pdma_add_resource() may be called multiple times | ||
| 89 | * by a driver and may register the percpu_kill devm action multiple | ||
| 90 | * times. We only want the first action to actually kill the | ||
| 91 | * percpu_ref. | ||
| 92 | */ | ||
| 93 | if (percpu_ref_is_dying(ref)) | ||
| 94 | return; | ||
| 95 | |||
| 96 | percpu_ref_kill(ref); | 95 | percpu_ref_kill(ref); |
| 97 | } | 96 | } |
| 98 | 97 | ||
| 98 | static void pci_p2pdma_percpu_cleanup(struct percpu_ref *ref) | ||
| 99 | { | ||
| 100 | struct p2pdma_pagemap *p2p_pgmap = to_p2p_pgmap(ref); | ||
| 101 | |||
| 102 | wait_for_completion(&p2p_pgmap->ref_done); | ||
| 103 | percpu_ref_exit(&p2p_pgmap->ref); | ||
| 104 | } | ||
| 105 | |||
| 99 | static void pci_p2pdma_release(void *data) | 106 | static void pci_p2pdma_release(void *data) |
| 100 | { | 107 | { |
| 101 | struct pci_dev *pdev = data; | 108 | struct pci_dev *pdev = data; |
| 109 | struct pci_p2pdma *p2pdma = pdev->p2pdma; | ||
| 102 | 110 | ||
| 103 | if (!pdev->p2pdma) | 111 | if (!p2pdma) |
| 104 | return; | 112 | return; |
| 105 | 113 | ||
| 106 | wait_for_completion(&pdev->p2pdma->devmap_ref_done); | 114 | /* Flush and disable pci_alloc_p2p_mem() */ |
| 107 | percpu_ref_exit(&pdev->p2pdma->devmap_ref); | 115 | pdev->p2pdma = NULL; |
| 116 | synchronize_rcu(); | ||
| 108 | 117 | ||
| 109 | gen_pool_destroy(pdev->p2pdma->pool); | 118 | gen_pool_destroy(p2pdma->pool); |
| 110 | sysfs_remove_group(&pdev->dev.kobj, &p2pmem_group); | 119 | sysfs_remove_group(&pdev->dev.kobj, &p2pmem_group); |
| 111 | pdev->p2pdma = NULL; | ||
| 112 | } | 120 | } |
| 113 | 121 | ||
| 114 | static int pci_p2pdma_setup(struct pci_dev *pdev) | 122 | static int pci_p2pdma_setup(struct pci_dev *pdev) |
| @@ -124,12 +132,6 @@ static int pci_p2pdma_setup(struct pci_dev *pdev) · 9 unmodified lines | |||
| 124 | if (!p2p->pool) | 132 | if (!p2p->pool) |
| 125 | goto out; | 133 | goto out; |
| 126 | 134 | ||
| 127 | init_completion(&p2p->devmap_ref_done); | ||
| 128 | error = percpu_ref_init(&p2p->devmap_ref, | ||
| 129 | pci_p2pdma_percpu_release, 0, GFP_KERNEL); | ||
| 130 | if (error) | ||
| 131 | goto out_pool_destroy; | ||
| 132 | |||
| 133 | error = devm_add_action_or_reset(&pdev->dev, pci_p2pdma_release, pdev); | 135 | error = devm_add_action_or_reset(&pdev->dev, pci_p2pdma_release, pdev); |
| 134 | if (error) | 136 | if (error) |
| 135 | goto out_pool_destroy; | 137 | goto out_pool_destroy; |
| @@ -163,6 +165,7 @@ out: · 27 unmodified lines | |||
| 163 | int pci_p2pdma_add_resource(struct pci_dev *pdev, int bar, size_t size, | 165 | int pci_p2pdma_add_resource(struct pci_dev *pdev, int bar, size_t size, |
| 164 | u64 offset) | 166 | u64 offset) |
| 165 | { | 167 | { |
| 168 | struct p2pdma_pagemap *p2p_pgmap; | ||
| 166 | struct dev_pagemap *pgmap; | 169 | struct dev_pagemap *pgmap; |
| 167 | void *addr; | 170 | void *addr; |
| 168 | int error; | 171 | int error; |
| @@ -185,18 +188,27 @@ int pci_p2pdma_add_resource(struct pci_dev *pdev, int bar, size_t size, · 16 unmodified lines | |||
| 185 | return error; | 188 | return error; |
| 186 | } | 189 | } |
| 187 | 190 | ||
| 188 | pgmap = devm_kzalloc(&pdev->dev, sizeof(*pgmap), GFP_KERNEL); | 191 | p2p_pgmap = devm_kzalloc(&pdev->dev, sizeof(*p2p_pgmap), GFP_KERNEL); |
| 189 | if (!pgmap) | 192 | if (!p2p_pgmap) |
| 190 | return -ENOMEM; | 193 | return -ENOMEM; |
| 191 | 194 | ||
| 195 | init_completion(&p2p_pgmap->ref_done); | ||
| 196 | error = percpu_ref_init(&p2p_pgmap->ref, | ||
| 197 | pci_p2pdma_percpu_release, 0, GFP_KERNEL); | ||
| 198 | if (error) | ||
| 199 | goto pgmap_free; | ||
| 200 | |||
| 201 | pgmap = &p2p_pgmap->pgmap; | ||
| 202 | |||
| 192 | pgmap->res.start = pci_resource_start(pdev, bar) + offset; | 203 | pgmap->res.start = pci_resource_start(pdev, bar) + offset; |
| 193 | pgmap->res.end = pgmap->res.start + size - 1; | 204 | pgmap->res.end = pgmap->res.start + size - 1; |
| 194 | pgmap->res.flags = pci_resource_flags(pdev, bar); | 205 | pgmap->res.flags = pci_resource_flags(pdev, bar); |
| 195 | pgmap->ref = &pdev->p2pdma->devmap_ref; | 206 | pgmap->ref = &p2p_pgmap->ref; |
| 196 | pgmap->type = MEMORY_DEVICE_PCI_P2PDMA; | 207 | pgmap->type = MEMORY_DEVICE_PCI_P2PDMA; |
| 197 | pgmap->pci_p2pdma_bus_offset = pci_bus_address(pdev, bar) - | 208 | pgmap->pci_p2pdma_bus_offset = pci_bus_address(pdev, bar) - |
| 198 | pci_resource_start(pdev, bar); | 209 | pci_resource_start(pdev, bar); |
| 199 | pgmap->kill = pci_p2pdma_percpu_kill; | 210 | pgmap->kill = pci_p2pdma_percpu_kill; |
| 211 | pgmap->cleanup = pci_p2pdma_percpu_cleanup; | ||
| 200 | 212 | ||
| 201 | addr = devm_memremap_pages(&pdev->dev, pgmap); | 213 | addr = devm_memremap_pages(&pdev->dev, pgmap); |
| 202 | if (IS_ERR(addr)) { | 214 | if (IS_ERR(addr)) { |
| @@ -204,19 +216,22 @@ int pci_p2pdma_add_resource(struct pci_dev *pdev, int bar, size_t size, · 1 unmodified line | |||
| 204 | goto pgmap_free; | 216 | goto pgmap_free; |
| 205 | } | 217 | } |
| 206 | 218 | ||
| 207 | error = gen_pool_add_virt(pdev->p2pdma->pool, (unsigned long)addr, | 219 | error = gen_pool_add_owner(pdev->p2pdma->pool, (unsigned long)addr, |
| 208 | pci_bus_address(pdev, bar) + offset, | 220 | pci_bus_address(pdev, bar) + offset, |
| 209 | resource_size(&pgmap->res), dev_to_node(&pdev->dev)); | 221 | resource_size(&pgmap->res), dev_to_node(&pdev->dev), |
| 222 | &p2p_pgmap->ref); | ||
| 210 | if (error) | 223 | if (error) |
| 211 | goto pgmap_free; | 224 | goto pages_free; |
| 212 | 225 | ||
| 213 | pci_info(pdev, "added peer-to-peer DMA memory %pR\n", | 226 | pci_info(pdev, "added peer-to-peer DMA memory %pR\n", |
| 214 | &pgmap->res); | 227 | &pgmap->res); |
| 215 | 228 | ||
| 216 | return 0; | 229 | return 0; |
| 217 | 230 | ||
| 231 | pages_free: | ||
| 232 | devm_memunmap_pages(&pdev->dev, pgmap); | ||
| 218 | pgmap_free: | 233 | pgmap_free: |
| 219 | devm_kfree(&pdev->dev, pgmap); | 234 | devm_kfree(&pdev->dev, p2p_pgmap); |
| 220 | return error; | 235 | return error; |
| 221 | } | 236 | } |
| 222 | EXPORT_SYMBOL_GPL(pci_p2pdma_add_resource); | 237 | EXPORT_SYMBOL_GPL(pci_p2pdma_add_resource); |
| @@ -585,19 +600,30 @@ EXPORT_SYMBOL_GPL(pci_p2pmem_find_many); · 362 unmodified lines | |||
| 585 | */ | 600 | */ |
| 586 | void *pci_alloc_p2pmem(struct pci_dev *pdev, size_t size) | 601 | void *pci_alloc_p2pmem(struct pci_dev *pdev, size_t size) |
| 587 | { | 602 | { |
| 588 | void *ret; | 603 | void *ret = NULL; |
| 604 | struct percpu_ref *ref; | ||
| 589 | 605 | ||
| 606 | /* | ||
| 607 | * Pairs with synchronize_rcu() in pci_p2pdma_release() to | ||
| 608 | * ensure pdev->p2pdma is non-NULL for the duration of the | ||
| 609 | * read-lock. | ||
| 610 | */ | ||
| 611 | rcu_read_lock(); | ||
| 590 | if (unlikely(!pdev->p2pdma)) | 612 | if (unlikely(!pdev->p2pdma)) |
| 591 | return NULL; | 613 | goto out; |
| 592 | |||
| 593 | if (unlikely(!percpu_ref_tryget_live(&pdev->p2pdma->devmap_ref))) | ||
| 594 | return NULL; | ||
| 595 | |||
| 596 | ret = (void *)gen_pool_alloc(pdev->p2pdma->pool, size); | ||
| 597 | 614 | ||
| 598 | if (unlikely(!ret)) | 615 | ret = (void *)gen_pool_alloc_owner(pdev->p2pdma->pool, size, |
| 599 | percpu_ref_put(&pdev->p2pdma->devmap_ref); | 616 | (void **) &ref); |
| 617 | if (!ret) | ||
| 618 | goto out; | ||
| 600 | 619 | ||
| 620 | if (unlikely(!percpu_ref_tryget_live(ref))) { | ||
| 621 | gen_pool_free(pdev->p2pdma->pool, (unsigned long) ret, size); | ||
| 622 | ret = NULL; | ||
| 623 | goto out; | ||
| 624 | } | ||
| 625 | out: | ||
| 626 | rcu_read_unlock(); | ||
| 601 | return ret; | 627 | return ret; |
| 602 | } | 628 | } |
| 603 | EXPORT_SYMBOL_GPL(pci_alloc_p2pmem); | 629 | EXPORT_SYMBOL_GPL(pci_alloc_p2pmem); |
| @@ -610,8 +636,11 @@ EXPORT_SYMBOL_GPL(pci_alloc_p2pmem); · 6 unmodified lines | |||
| 610 | */ | 636 | */ |
| 611 | void pci_free_p2pmem(struct pci_dev *pdev, void *addr, size_t size) | 637 | void pci_free_p2pmem(struct pci_dev *pdev, void *addr, size_t size) |
| 612 | { | 638 | { |
| 613 | gen_pool_free(pdev->p2pdma->pool, (uintptr_t)addr, size); | 639 | struct percpu_ref *ref; |
| 614 | percpu_ref_put(&pdev->p2pdma->devmap_ref); | 640 | |
| 641 | gen_pool_free_owner(pdev->p2pdma->pool, (uintptr_t)addr, size, | ||
| 642 | (void **) &ref); | ||
| 643 | percpu_ref_put(ref); | ||
| 615 | } | 644 | } |
| 616 | EXPORT_SYMBOL_GPL(pci_free_p2pmem); | 645 | EXPORT_SYMBOL_GPL(pci_free_p2pmem); |
| 617 | 646 | ||
| @@ -296,6 +296,18 @@ int ocfs2_dentry_attach_lock(struct dentry *dentry, · 295 unmodified lines | |||
| 296 | 296 | ||
| 297 | out_attach: | 297 | out_attach: |
| 298 | spin_lock(&dentry_attach_lock); | 298 | spin_lock(&dentry_attach_lock); |
| 299 | if (unlikely(dentry->d_fsdata && !alias)) { | ||
| 300 | /* d_fsdata is set by a racing thread which is doing | ||
| 301 | * the same thing as this thread is doing. Leave the racing | ||
| 302 | * thread going ahead and we return here. | ||
| 303 | */ | ||
| 304 | spin_unlock(&dentry_attach_lock); | ||
| 305 | iput(dl->dl_inode); | ||
| 306 | ocfs2_lock_res_free(&dl->dl_lockres); | ||
| 307 | kfree(dl); | ||
| 308 | return 0; | ||
| 309 | } | ||
| 310 | |||
| 299 | dentry->d_fsdata = dl; | 311 | dentry->d_fsdata = dl; |
| 300 | dl->dl_count++; | 312 | dl->dl_count++; |
| 301 | spin_unlock(&dentry_attach_lock); | 313 | spin_unlock(&dentry_attach_lock); |
| @@ -713,6 +713,7 @@ void __iomem *devm_of_iomap(struct device *dev, · 712 unmodified lines | |||
| 713 | /* allows to add/remove a custom action to devres stack */ | 713 | /* allows to add/remove a custom action to devres stack */ |
| 714 | int devm_add_action(struct device *dev, void (*action)(void *), void *data); | 714 | int devm_add_action(struct device *dev, void (*action)(void *), void *data); |
| 715 | void devm_remove_action(struct device *dev, void (*action)(void *), void *data); | 715 | void devm_remove_action(struct device *dev, void (*action)(void *), void *data); |
| 716 | void devm_release_action(struct device *dev, void (*action)(void *), void *data); | ||
| 716 | 717 | ||
| 717 | static inline int devm_add_action_or_reset(struct device *dev, | 718 | static inline int devm_add_action_or_reset(struct device *dev, |
| 718 | void (*action)(void *), void *data) | 719 | void (*action)(void *), void *data) |
| @@ -75,6 +75,7 @@ struct gen_pool_chunk { · 74 unmodified lines | |||
| 75 | struct list_head next_chunk; /* next chunk in pool */ | 75 | struct list_head next_chunk; /* next chunk in pool */ |
| 76 | atomic_long_t avail; | 76 | atomic_long_t avail; |
| 77 | phys_addr_t phys_addr; /* physical starting address of memory chunk */ | 77 | phys_addr_t phys_addr; /* physical starting address of memory chunk */ |
| 78 | void *owner; /* private data to retrieve at alloc time */ | ||
| 78 | unsigned long start_addr; /* start address of memory chunk */ | 79 | unsigned long start_addr; /* start address of memory chunk */ |
| 79 | unsigned long end_addr; /* end address of memory chunk (inclusive) */ | 80 | unsigned long end_addr; /* end address of memory chunk (inclusive) */ |
| 80 | unsigned long bits[0]; /* bitmap for allocating memory chunk */ | 81 | unsigned long bits[0]; /* bitmap for allocating memory chunk */ |
| @@ -96,8 +97,15 @@ struct genpool_data_fixed { · 15 unmodified lines | |||
| 96 | 97 | ||
| 97 | extern struct gen_pool *gen_pool_create(int, int); | 98 | extern struct gen_pool *gen_pool_create(int, int); |
| 98 | extern phys_addr_t gen_pool_virt_to_phys(struct gen_pool *pool, unsigned long); | 99 | extern phys_addr_t gen_pool_virt_to_phys(struct gen_pool *pool, unsigned long); |
| 99 | extern int gen_pool_add_virt(struct gen_pool *, unsigned long, phys_addr_t, | 100 | extern int gen_pool_add_owner(struct gen_pool *, unsigned long, phys_addr_t, |
| 100 | size_t, int); | 101 | size_t, int, void *); |
| 102 | |||
| 103 | static inline int gen_pool_add_virt(struct gen_pool *pool, unsigned long addr, | ||
| 104 | phys_addr_t phys, size_t size, int nid) | ||
| 105 | { | ||
| 106 | return gen_pool_add_owner(pool, addr, phys, size, nid, NULL); | ||
| 107 | } | ||
| 108 | |||
| 101 | /** | 109 | /** |
| 102 | * gen_pool_add - add a new chunk of special memory to the pool | 110 | * gen_pool_add - add a new chunk of special memory to the pool |
| 103 | * @pool: pool to add new memory chunk to | 111 | * @pool: pool to add new memory chunk to |
| @@ -116,12 +124,47 @@ static inline int gen_pool_add(struct gen_pool *pool, unsigned long addr, · 12 unmodified lines | |||
| 116 | return gen_pool_add_virt(pool, addr, -1, size, nid); | 124 | return gen_pool_add_virt(pool, addr, -1, size, nid); |
| 117 | } | 125 | } |
| 118 | extern void gen_pool_destroy(struct gen_pool *); | 126 | extern void gen_pool_destroy(struct gen_pool *); |
| 119 | extern unsigned long gen_pool_alloc(struct gen_pool *, size_t); | 127 | unsigned long gen_pool_alloc_algo_owner(struct gen_pool *pool, size_t size, |
| 120 | extern unsigned long gen_pool_alloc_algo(struct gen_pool *, size_t, | 128 | genpool_algo_t algo, void *data, void **owner); |
| 121 | genpool_algo_t algo, void *data); | 129 | |
| 130 | static inline unsigned long gen_pool_alloc_owner(struct gen_pool *pool, | ||
| 131 | size_t size, void **owner) | ||
| 132 | { | ||
| 133 | return gen_pool_alloc_algo_owner(pool, size, pool->algo, pool->data, | ||
| 134 | owner); | ||
| 135 | } | ||
| 136 | |||
| 137 | static inline unsigned long gen_pool_alloc_algo(struct gen_pool *pool, | ||
| 138 | size_t size, genpool_algo_t algo, void *data) | ||
| 139 | { | ||
| 140 | return gen_pool_alloc_algo_owner(pool, size, algo, data, NULL); | ||
| 141 | } | ||
| 142 | |||
| 143 | /** | ||
| 144 | * gen_pool_alloc - allocate special memory from the pool | ||
| 145 | * @pool: pool to allocate from | ||
| 146 | * @size: number of bytes to allocate from the pool | ||
| 147 | * | ||
| 148 | * Allocate the requested number of bytes from the specified pool. | ||
| 149 | * Uses the pool allocation function (with first-fit algorithm by default). | ||
| 150 | * Can not be used in NMI handler on architectures without | ||
| 151 | * NMI-safe cmpxchg implementation. | ||
| 152 | */ | ||
| 153 | static inline unsigned long gen_pool_alloc(struct gen_pool *pool, size_t size) | ||
| 154 | { | ||
| 155 | return gen_pool_alloc_algo(pool, size, pool->algo, pool->data); | ||
| 156 | } | ||
| 157 | |||
| 122 | extern void *gen_pool_dma_alloc(struct gen_pool *pool, size_t size, | 158 | extern void *gen_pool_dma_alloc(struct gen_pool *pool, size_t size, |
| 123 | dma_addr_t *dma); | 159 | dma_addr_t *dma); |
| 124 | extern void gen_pool_free(struct gen_pool *, unsigned long, size_t); | 160 | extern void gen_pool_free_owner(struct gen_pool *pool, unsigned long addr, |
| 161 | size_t size, void **owner); | ||
| 162 | static inline void gen_pool_free(struct gen_pool *pool, unsigned long addr, | ||
| 163 | size_t size) | ||
| 164 | { | ||
| 165 | gen_pool_free_owner(pool, addr, size, NULL); | ||
| 166 | } | ||
| 167 | |||
| 125 | extern void gen_pool_for_each_chunk(struct gen_pool *, | 168 | extern void gen_pool_for_each_chunk(struct gen_pool *, |
| 126 | void (*)(struct gen_pool *, struct gen_pool_chunk *, void *), void *); | 169 | void (*)(struct gen_pool *, struct gen_pool_chunk *, void *), void *); |
| 127 | extern size_t gen_pool_avail(struct gen_pool *); | 170 | extern size_t gen_pool_avail(struct gen_pool *); |
| @@ -117,9 +117,12 @@ struct memcg_shrinker_map { · 116 unmodified lines | |||
| 117 | struct mem_cgroup_per_node { | 117 | struct mem_cgroup_per_node { |
| 118 | struct lruvec lruvec; | 118 | struct lruvec lruvec; |
| 119 | 119 | ||
| 120 | /* Legacy local VM stats */ | ||
| 121 | struct lruvec_stat __percpu *lruvec_stat_local; | ||
| 122 | |||
| 123 | /* Subtree VM stats (batched updates) */ | ||
| 120 | struct lruvec_stat __percpu *lruvec_stat_cpu; | 124 | struct lruvec_stat __percpu *lruvec_stat_cpu; |
| 121 | atomic_long_t lruvec_stat[NR_VM_NODE_STAT_ITEMS]; | 125 | atomic_long_t lruvec_stat[NR_VM_NODE_STAT_ITEMS]; |
| 122 | atomic_long_t lruvec_stat_local[NR_VM_NODE_STAT_ITEMS]; | ||
| 123 | 126 | ||
| 124 | unsigned long lru_zone_size[MAX_NR_ZONES][NR_LRU_LISTS]; | 127 | unsigned long lru_zone_size[MAX_NR_ZONES][NR_LRU_LISTS]; |
| 125 | 128 | ||
| @@ -265,17 +268,18 @@ struct mem_cgroup { · 139 unmodified lines | |||
| 265 | atomic_t moving_account; | 268 | atomic_t moving_account; |
| 266 | struct task_struct *move_lock_task; | 269 | struct task_struct *move_lock_task; |
| 267 | 270 | ||
| 268 | /* memory.stat */ | 271 | /* Legacy local VM stats and events */ |
| 272 | struct memcg_vmstats_percpu __percpu *vmstats_local; | ||
| 273 | |||
| 274 | /* Subtree VM stats and events (batched updates) */ | ||
| 269 | struct memcg_vmstats_percpu __percpu *vmstats_percpu; | 275 | struct memcg_vmstats_percpu __percpu *vmstats_percpu; |
| 270 | 276 | ||
| 271 | MEMCG_PADDING(_pad2_); | 277 | MEMCG_PADDING(_pad2_); |
| 272 | 278 | ||
| 273 | atomic_long_t vmstats[MEMCG_NR_STAT]; | 279 | atomic_long_t vmstats[MEMCG_NR_STAT]; |
| 274 | atomic_long_t vmstats_local[MEMCG_NR_STAT]; | ||
| 275 | |||
| 276 | atomic_long_t vmevents[NR_VM_EVENT_ITEMS]; | 280 | atomic_long_t vmevents[NR_VM_EVENT_ITEMS]; |
| 277 | atomic_long_t vmevents_local[NR_VM_EVENT_ITEMS]; | ||
| 278 | 281 | ||
| 282 | /* memory.events */ | ||
| 279 | atomic_long_t memory_events[MEMCG_NR_MEMORY_EVENTS]; | 283 | atomic_long_t memory_events[MEMCG_NR_MEMORY_EVENTS]; |
| 280 | 284 | ||
| 281 | unsigned long socket_pressure; | 285 | unsigned long socket_pressure; |
| @@ -567,7 +571,11 @@ static inline unsigned long memcg_page_state(struct mem_cgroup *memcg, int idx) · 285 unmodified lines | |||
| 567 | static inline unsigned long memcg_page_state_local(struct mem_cgroup *memcg, | 571 | static inline unsigned long memcg_page_state_local(struct mem_cgroup *memcg, |
| 568 | int idx) | 572 | int idx) |
| 569 | { | 573 | { |
| 570 | long x = atomic_long_read(&memcg->vmstats_local[idx]); | 574 | long x = 0; |
| 575 | int cpu; | ||
| 576 | |||
| 577 | for_each_possible_cpu(cpu) | ||
| 578 | x += per_cpu(memcg->vmstats_local->stat[idx], cpu); | ||
| 571 | #ifdef CONFIG_SMP | 579 | #ifdef CONFIG_SMP |
| 572 | if (x < 0) | 580 | if (x < 0) |
| 573 | x = 0; | 581 | x = 0; |
| @@ -641,13 +649,15 @@ static inline unsigned long lruvec_page_state_local(struct lruvec *lruvec, · 67 unmodified lines | |||
| 641 | enum node_stat_item idx) | 649 | enum node_stat_item idx) |
| 642 | { | 650 | { |
| 643 | struct mem_cgroup_per_node *pn; | 651 | struct mem_cgroup_per_node *pn; |
| 644 | long x; | 652 | long x = 0; |
| 653 | int cpu; | ||
| 645 | 654 | ||
| 646 | if (mem_cgroup_disabled()) | 655 | if (mem_cgroup_disabled()) |
| 647 | return node_page_state(lruvec_pgdat(lruvec), idx); | 656 | return node_page_state(lruvec_pgdat(lruvec), idx); |
| 648 | 657 | ||
| 649 | pn = container_of(lruvec, struct mem_cgroup_per_node, lruvec); | 658 | pn = container_of(lruvec, struct mem_cgroup_per_node, lruvec); |
| 650 | x = atomic_long_read(&pn->lruvec_stat_local[idx]); | 659 | for_each_possible_cpu(cpu) |
| 660 | x += per_cpu(pn->lruvec_stat_local->count[idx], cpu); | ||
| 651 | #ifdef CONFIG_SMP | 661 | #ifdef CONFIG_SMP |
| 652 | if (x < 0) | 662 | if (x < 0) |
| 653 | x = 0; | 663 | x = 0; |
| @@ -81,6 +81,7 @@ typedef void (*dev_page_free_t)(struct page *page, void *data); · 80 unmodified lines | |||
| 81 | * @res: physical address range covered by @ref | 81 | * @res: physical address range covered by @ref |
| 82 | * @ref: reference count that pins the devm_memremap_pages() mapping | 82 | * @ref: reference count that pins the devm_memremap_pages() mapping |
| 83 | * @kill: callback to transition @ref to the dead state | 83 | * @kill: callback to transition @ref to the dead state |
| 84 | * @cleanup: callback to wait for @ref to be idle and reap it | ||
| 84 | * @dev: host device of the mapping for debug | 85 | * @dev: host device of the mapping for debug |
| 85 | * @data: private data pointer for page_free() | 86 | * @data: private data pointer for page_free() |
| 86 | * @type: memory type: see MEMORY_* in memory_hotplug.h | 87 | * @type: memory type: see MEMORY_* in memory_hotplug.h |
| @@ -92,6 +93,7 @@ struct dev_pagemap { · 5 unmodified lines | |||
| 92 | struct resource res; | 93 | struct resource res; |
| 93 | struct percpu_ref *ref; | 94 | struct percpu_ref *ref; |
| 94 | void (*kill)(struct percpu_ref *ref); | 95 | void (*kill)(struct percpu_ref *ref); |
| 96 | void (*cleanup)(struct percpu_ref *ref); | ||
| 95 | struct device *dev; | 97 | struct device *dev; |
| 96 | void *data; | 98 | void *data; |
| 97 | enum memory_type type; | 99 | enum memory_type type; |
| @@ -100,6 +102,7 @@ struct dev_pagemap { · 2 unmodified lines | |||
| 100 | 102 | ||
| 101 | #ifdef CONFIG_ZONE_DEVICE | 103 | #ifdef CONFIG_ZONE_DEVICE |
| 102 | void *devm_memremap_pages(struct device *dev, struct dev_pagemap *pgmap); | 104 | void *devm_memremap_pages(struct device *dev, struct dev_pagemap *pgmap); |
| 105 | void devm_memunmap_pages(struct device *dev, struct dev_pagemap *pgmap); | ||
| 103 | struct dev_pagemap *get_dev_pagemap(unsigned long pfn, | 106 | struct dev_pagemap *get_dev_pagemap(unsigned long pfn, |
| 104 | struct dev_pagemap *pgmap); | 107 | struct dev_pagemap *pgmap); |
| 105 | 108 | ||
| @@ -118,6 +121,11 @@ static inline void *devm_memremap_pages(struct device *dev, · 12 unmodified lines | |||
| 118 | return ERR_PTR(-ENXIO); | 121 | return ERR_PTR(-ENXIO); |
| 119 | } | 122 | } |
| 120 | 123 | ||
| 124 | static inline void devm_memunmap_pages(struct device *dev, | ||
| 125 | struct dev_pagemap *pgmap) | ||
| 126 | { | ||
| 127 | } | ||
| 128 | |||
| 121 | static inline struct dev_pagemap *get_dev_pagemap(unsigned long pfn, | 129 | static inline struct dev_pagemap *get_dev_pagemap(unsigned long pfn, |
| 122 | struct dev_pagemap *pgmap) | 130 | struct dev_pagemap *pgmap) |
| 123 | { | 131 | { |
| @@ -54,6 +54,10 @@ static inline void mmdrop(struct mm_struct *mm) · 53 unmodified lines | |||
| 54 | * followed by taking the mmap_sem for writing before modifying the | 54 | * followed by taking the mmap_sem for writing before modifying the |
| 55 | * vmas or anything the coredump pretends not to change from under it. | 55 | * vmas or anything the coredump pretends not to change from under it. |
| 56 | * | 56 | * |
| 57 | * It also has to be called when mmgrab() is used in the context of | ||
| 58 | * the process, but then the mm_count refcount is transferred outside | ||
| 59 | * the context of the process to run down_write() on that pinned mm. | ||
| 60 | * | ||
| 57 | * NOTE: find_extend_vma() called from GUP context is the only place | 61 | * NOTE: find_extend_vma() called from GUP context is the only place |
| 58 | * that can modify the "mm" (notably the vm_start/end) under mmap_sem | 62 | * that can modify the "mm" (notably the vm_start/end) under mmap_sem |
| 59 | * for reading and outside the context of the process, so it is also | 63 | * for reading and outside the context of the process, so it is also |
| @@ -95,6 +95,7 @@ static void devm_memremap_pages_release(void *data) · 94 unmodified lines | |||
| 95 | pgmap->kill(pgmap->ref); | 95 | pgmap->kill(pgmap->ref); |
| 96 | for_each_device_pfn(pfn, pgmap) | 96 | for_each_device_pfn(pfn, pgmap) |
| 97 | put_page(pfn_to_page(pfn)); | 97 | put_page(pfn_to_page(pfn)); |
| 98 | pgmap->cleanup(pgmap->ref); | ||
| 98 | 99 | ||
| 99 | /* pages are dead and unused, undo the arch mapping */ | 100 | /* pages are dead and unused, undo the arch mapping */ |
| 100 | align_start = res->start & ~(SECTION_SIZE - 1); | 101 | align_start = res->start & ~(SECTION_SIZE - 1); |
| @@ -133,8 +134,8 @@ static void devm_memremap_pages_release(void *data) · 32 unmodified lines | |||
| 133 | * 2/ The altmap field may optionally be initialized, in which case altmap_valid | 134 | * 2/ The altmap field may optionally be initialized, in which case altmap_valid |
| 134 | * must be set to true | 135 | * must be set to true |
| 135 | * | 136 | * |
| 136 | * 3/ pgmap->ref must be 'live' on entry and will be killed at | 137 | * 3/ pgmap->ref must be 'live' on entry and will be killed and reaped |
| 137 | * devm_memremap_pages_release() time, or if this routine fails. | 138 | * at devm_memremap_pages_release() time, or if this routine fails. |
| 138 | * | 139 | * |
| 139 | * 4/ res is expected to be a host memory range that could feasibly be | 140 | * 4/ res is expected to be a host memory range that could feasibly be |
| 140 | * treated as a "System RAM" range, i.e. not a device mmio range, but | 141 | * treated as a "System RAM" range, i.e. not a device mmio range, but |
| @@ -156,8 +157,10 @@ void *devm_memremap_pages(struct device *dev, struct dev_pagemap *pgmap) · 15 unmodified lines | |||
| 156 | pgprot_t pgprot = PAGE_KERNEL; | 157 | pgprot_t pgprot = PAGE_KERNEL; |
| 157 | int error, nid, is_ram; | 158 | int error, nid, is_ram; |
| 158 | 159 | ||
| 159 | if (!pgmap->ref || !pgmap->kill) | 160 | if (!pgmap->ref || !pgmap->kill || !pgmap->cleanup) { |
| 161 | WARN(1, "Missing reference count teardown definition\n"); | ||
| 160 | return ERR_PTR(-EINVAL); | 162 | return ERR_PTR(-EINVAL); |
| 163 | } | ||
| 161 | 164 | ||
| 162 | align_start = res->start & ~(SECTION_SIZE - 1); | 165 | align_start = res->start & ~(SECTION_SIZE - 1); |
| 163 | align_size = ALIGN(res->start + resource_size(res), SECTION_SIZE) | 166 | align_size = ALIGN(res->start + resource_size(res), SECTION_SIZE) |
| @@ -168,14 +171,16 @@ void *devm_memremap_pages(struct device *dev, struct dev_pagemap *pgmap) · 4 unmodified lines | |||
| 168 | if (conflict_pgmap) { | 171 | if (conflict_pgmap) { |
| 169 | dev_WARN(dev, "Conflicting mapping in same section\n"); | 172 | dev_WARN(dev, "Conflicting mapping in same section\n"); |
| 170 | put_dev_pagemap(conflict_pgmap); | 173 | put_dev_pagemap(conflict_pgmap); |
| 171 | return ERR_PTR(-ENOMEM); | 174 | error = -ENOMEM; |
| 175 | goto err_array; | ||
| 172 | } | 176 | } |
| 173 | 177 | ||
| 174 | conflict_pgmap = get_dev_pagemap(PHYS_PFN(align_end), NULL); | 178 | conflict_pgmap = get_dev_pagemap(PHYS_PFN(align_end), NULL); |
| 175 | if (conflict_pgmap) { | 179 | if (conflict_pgmap) { |
| 176 | dev_WARN(dev, "Conflicting mapping in same section\n"); | 180 | dev_WARN(dev, "Conflicting mapping in same section\n"); |
| 177 | put_dev_pagemap(conflict_pgmap); | 181 | put_dev_pagemap(conflict_pgmap); |
| 178 | return ERR_PTR(-ENOMEM); | 182 | error = -ENOMEM; |
| 183 | goto err_array; | ||
| 179 | } | 184 | } |
| 180 | 185 | ||
| 181 | is_ram = region_intersects(align_start, align_size, | 186 | is_ram = region_intersects(align_start, align_size, |
| @@ -267,10 +272,18 @@ void *devm_memremap_pages(struct device *dev, struct dev_pagemap *pgmap) · 85 unmodified lines | |||
| 267 | pgmap_array_delete(res); | 272 | pgmap_array_delete(res); |
| 268 | err_array: | 273 | err_array: |
| 269 | pgmap->kill(pgmap->ref); | 274 | pgmap->kill(pgmap->ref); |
| 275 | pgmap->cleanup(pgmap->ref); | ||
| 276 | |||
| 270 | return ERR_PTR(error); | 277 | return ERR_PTR(error); |
| 271 | } | 278 | } |
| 272 | EXPORT_SYMBOL_GPL(devm_memremap_pages); | 279 | EXPORT_SYMBOL_GPL(devm_memremap_pages); |
| 273 | 280 | ||
| 281 | void devm_memunmap_pages(struct device *dev, struct dev_pagemap *pgmap) | ||
| 282 | { | ||
| 283 | devm_release_action(dev, devm_memremap_pages_release, pgmap); | ||
| 284 | } | ||
| 285 | EXPORT_SYMBOL_GPL(devm_memunmap_pages); | ||
| 286 | |||
| 274 | unsigned long vmem_altmap_offset(struct vmem_altmap *altmap) | 287 | unsigned long vmem_altmap_offset(struct vmem_altmap *altmap) |
| 275 | { | 288 | { |
| 276 | /* number of pfns from base where pfn_to_page() is valid */ | 289 | /* number of pfns from base where pfn_to_page() is valid */ |
| @@ -168,20 +168,21 @@ struct gen_pool *gen_pool_create(int min_alloc_order, int nid) · 167 unmodified lines | |||
| 168 | EXPORT_SYMBOL(gen_pool_create); | 168 | EXPORT_SYMBOL(gen_pool_create); |
| 169 | 169 | ||
| 170 | /** | 170 | /** |
| 171 | * gen_pool_add_virt - add a new chunk of special memory to the pool | 171 | * gen_pool_add_owner- add a new chunk of special memory to the pool |
| 172 | * @pool: pool to add new memory chunk to | 172 | * @pool: pool to add new memory chunk to |
| 173 | * @virt: virtual starting address of memory chunk to add to pool | 173 | * @virt: virtual starting address of memory chunk to add to pool |
| 174 | * @phys: physical starting address of memory chunk to add to pool | 174 | * @phys: physical starting address of memory chunk to add to pool |
| 175 | * @size: size in bytes of the memory chunk to add to pool | 175 | * @size: size in bytes of the memory chunk to add to pool |
| 176 | * @nid: node id of the node the chunk structure and bitmap should be | 176 | * @nid: node id of the node the chunk structure and bitmap should be |
| 177 | * allocated on, or -1 | 177 | * allocated on, or -1 |
| 178 | * @owner: private data the publisher would like to recall at alloc time | ||
| 178 | * | 179 | * |
| 179 | * Add a new chunk of special memory to the specified pool. | 180 | * Add a new chunk of special memory to the specified pool. |
| 180 | * | 181 | * |
| 181 | * Returns 0 on success or a -ve errno on failure. | 182 | * Returns 0 on success or a -ve errno on failure. |
| 182 | */ | 183 | */ |
| 183 | int gen_pool_add_virt(struct gen_pool *pool, unsigned long virt, phys_addr_t phys, | 184 | int gen_pool_add_owner(struct gen_pool *pool, unsigned long virt, phys_addr_t phys, |
| 184 | size_t size, int nid) | 185 | size_t size, int nid, void *owner) |
| 185 | { | 186 | { |
| 186 | struct gen_pool_chunk *chunk; | 187 | struct gen_pool_chunk *chunk; |
| 187 | int nbits = size >> pool->min_alloc_order; | 188 | int nbits = size >> pool->min_alloc_order; |
| @@ -195,6 +196,7 @@ int gen_pool_add_virt(struct gen_pool *pool, unsigned long virt, phys_addr_t phy · 7 unmodified lines | |||
| 195 | chunk->phys_addr = phys; | 196 | chunk->phys_addr = phys; |
| 196 | chunk->start_addr = virt; | 197 | chunk->start_addr = virt; |
| 197 | chunk->end_addr = virt + size - 1; | 198 | chunk->end_addr = virt + size - 1; |
| 199 | chunk->owner = owner; | ||
| 198 | atomic_long_set(&chunk->avail, size); | 200 | atomic_long_set(&chunk->avail, size); |
| 199 | 201 | ||
| 200 | spin_lock(&pool->lock); | 202 | spin_lock(&pool->lock); |
| @@ -203,7 +205,7 @@ int gen_pool_add_virt(struct gen_pool *pool, unsigned long virt, phys_addr_t phy · 2 unmodified lines | |||
| 203 | 205 | ||
| 204 | return 0; | 206 | return 0; |
| 205 | } | 207 | } |
| 206 | EXPORT_SYMBOL(gen_pool_add_virt); | 208 | EXPORT_SYMBOL(gen_pool_add_owner); |
| 207 | 209 | ||
| 208 | /** | 210 | /** |
| 209 | * gen_pool_virt_to_phys - return the physical address of memory | 211 | * gen_pool_virt_to_phys - return the physical address of memory |
| @@ -260,35 +262,20 @@ void gen_pool_destroy(struct gen_pool *pool) · 50 unmodified lines | |||
| 260 | EXPORT_SYMBOL(gen_pool_destroy); | 262 | EXPORT_SYMBOL(gen_pool_destroy); |
| 261 | 263 | ||
| 262 | /** | 264 | /** |
| 263 | * gen_pool_alloc - allocate special memory from the pool | 265 | * gen_pool_alloc_algo_owner - allocate special memory from the pool |
| 264 | * @pool: pool to allocate from | ||
| 265 | * @size: number of bytes to allocate from the pool | ||
| 266 | * | ||
| 267 | * Allocate the requested number of bytes from the specified pool. | ||
| 268 | * Uses the pool allocation function (with first-fit algorithm by default). | ||
| 269 | * Can not be used in NMI handler on architectures without | ||
| 270 | * NMI-safe cmpxchg implementation. | ||
| 271 | */ | ||
| 272 | unsigned long gen_pool_alloc(struct gen_pool *pool, size_t size) | ||
| 273 | { | ||
| 274 | return gen_pool_alloc_algo(pool, size, pool->algo, pool->data); | ||
| 275 | } | ||
| 276 | EXPORT_SYMBOL(gen_pool_alloc); | ||
| 277 | |||
| 278 | /** | ||
| 279 | * gen_pool_alloc_algo - allocate special memory from the pool | ||
| 280 | * @pool: pool to allocate from | 266 | * @pool: pool to allocate from |
| 281 | * @size: number of bytes to allocate from the pool | 267 | * @size: number of bytes to allocate from the pool |
| 282 | * @algo: algorithm passed from caller | 268 | * @algo: algorithm passed from caller |
| 283 | * @data: data passed to algorithm | 269 | * @data: data passed to algorithm |
| 270 | * @owner: optionally retrieve the chunk owner | ||
| 284 | * | 271 | * |
| 285 | * Allocate the requested number of bytes from the specified pool. | 272 | * Allocate the requested number of bytes from the specified pool. |
| 286 | * Uses the pool allocation function (with first-fit algorithm by default). | 273 | * Uses the pool allocation function (with first-fit algorithm by default). |
| 287 | * Can not be used in NMI handler on architectures without | 274 | * Can not be used in NMI handler on architectures without |
| 288 | * NMI-safe cmpxchg implementation. | 275 | * NMI-safe cmpxchg implementation. |
| 289 | */ | 276 | */ |
| 290 | unsigned long gen_pool_alloc_algo(struct gen_pool *pool, size_t size, | 277 | unsigned long gen_pool_alloc_algo_owner(struct gen_pool *pool, size_t size, |
| 291 | genpool_algo_t algo, void *data) | 278 | genpool_algo_t algo, void *data, void **owner) |
| 292 | { | 279 | { |
| 293 | struct gen_pool_chunk *chunk; | 280 | struct gen_pool_chunk *chunk; |
| 294 | unsigned long addr = 0; | 281 | unsigned long addr = 0; |
| @@ -299,6 +286,9 @@ unsigned long gen_pool_alloc_algo(struct gen_pool *pool, size_t size, · 4 unmodified lines | |||
| 299 | BUG_ON(in_nmi()); | 286 | BUG_ON(in_nmi()); |
| 300 | #endif | 287 | #endif |
| 301 | 288 | ||
| 289 | if (owner) | ||
| 290 | *owner = NULL; | ||
| 291 | |||
| 302 | if (size == 0) | 292 | if (size == 0) |
| 303 | return 0; | 293 | return 0; |
| 304 | 294 | ||
| @@ -326,12 +316,14 @@ retry: · 21 unmodified lines | |||
| 326 | addr = chunk->start_addr + ((unsigned long)start_bit << order); | 316 | addr = chunk->start_addr + ((unsigned long)start_bit << order); |
| 327 | size = nbits << order; | 317 | size = nbits << order; |
| 328 | atomic_long_sub(size, &chunk->avail); | 318 | atomic_long_sub(size, &chunk->avail); |
| 319 | if (owner) | ||
| 320 | *owner = chunk->owner; | ||
| 329 | break; | 321 | break; |
| 330 | } | 322 | } |
| 331 | rcu_read_unlock(); | 323 | rcu_read_unlock(); |
| 332 | return addr; | 324 | return addr; |
| 333 | } | 325 | } |
| 334 | EXPORT_SYMBOL(gen_pool_alloc_algo); | 326 | EXPORT_SYMBOL(gen_pool_alloc_algo_owner); |
| 335 | 327 | ||
| 336 | /** | 328 | /** |
| 337 | * gen_pool_dma_alloc - allocate special memory from the pool for DMA usage | 329 | * gen_pool_dma_alloc - allocate special memory from the pool for DMA usage |
| @@ -367,12 +359,14 @@ EXPORT_SYMBOL(gen_pool_dma_alloc); · 29 unmodified lines | |||
| 367 | * @pool: pool to free to | 359 | * @pool: pool to free to |
| 368 | * @addr: starting address of memory to free back to pool | 360 | * @addr: starting address of memory to free back to pool |
| 369 | * @size: size in bytes of memory to free | 361 | * @size: size in bytes of memory to free |
| 362 | * @owner: private data stashed at gen_pool_add() time | ||
| 370 | * | 363 | * |
| 371 | * Free previously allocated special memory back to the specified | 364 | * Free previously allocated special memory back to the specified |
| 372 | * pool. Can not be used in NMI handler on architectures without | 365 | * pool. Can not be used in NMI handler on architectures without |
| 373 | * NMI-safe cmpxchg implementation. | 366 | * NMI-safe cmpxchg implementation. |
| 374 | */ | 367 | */ |
| 375 | void gen_pool_free(struct gen_pool *pool, unsigned long addr, size_t size) | 368 | void gen_pool_free_owner(struct gen_pool *pool, unsigned long addr, size_t size, |
| 369 | void **owner) | ||
| 376 | { | 370 | { |
| 377 | struct gen_pool_chunk *chunk; | 371 | struct gen_pool_chunk *chunk; |
| 378 | int order = pool->min_alloc_order; | 372 | int order = pool->min_alloc_order; |
| @@ -382,6 +376,9 @@ void gen_pool_free(struct gen_pool *pool, unsigned long addr, size_t size) · 3 unmodified lines | |||
| 382 | BUG_ON(in_nmi()); | 376 | BUG_ON(in_nmi()); |
| 383 | #endif | 377 | #endif |
| 384 | 378 | ||
| 379 | if (owner) | ||
| 380 | *owner = NULL; | ||
| 381 | |||
| 385 | nbits = (size + (1UL << order) - 1) >> order; | 382 | nbits = (size + (1UL << order) - 1) >> order; |
| 386 | rcu_read_lock(); | 383 | rcu_read_lock(); |
| 387 | list_for_each_entry_rcu(chunk, &pool->chunks, next_chunk) { | 384 | list_for_each_entry_rcu(chunk, &pool->chunks, next_chunk) { |
| @@ -392,6 +389,8 @@ void gen_pool_free(struct gen_pool *pool, unsigned long addr, size_t size) · 4 unmodified lines | |||
| 392 | BUG_ON(remain); | 389 | BUG_ON(remain); |
| 393 | size = nbits << order; | 390 | size = nbits << order; |
| 394 | atomic_long_add(size, &chunk->avail); | 391 | atomic_long_add(size, &chunk->avail); |
| 392 | if (owner) | ||
| 393 | *owner = chunk->owner; | ||
| 395 | rcu_read_unlock(); | 394 | rcu_read_unlock(); |
| 396 | return; | 395 | return; |
| 397 | } | 396 | } |
| @@ -399,7 +398,7 @@ void gen_pool_free(struct gen_pool *pool, unsigned long addr, size_t size) · 1 unmodified line | |||
| 399 | rcu_read_unlock(); | 398 | rcu_read_unlock(); |
| 400 | BUG(); | 399 | BUG(); |
| 401 | } | 400 | } |
| 402 | EXPORT_SYMBOL(gen_pool_free); | 401 | EXPORT_SYMBOL(gen_pool_free_owner); |
| 403 | 402 | ||
| 404 | /** | 403 | /** |
| 405 | * gen_pool_for_each_chunk - call func for every chunk of generic memory pool | 404 | * gen_pool_for_each_chunk - call func for every chunk of generic memory pool |
| @@ -1354,9 +1354,8 @@ static void hmm_devmem_ref_release(struct percpu_ref *ref) · 1353 unmodified lines | |||
| 1354 | complete(&devmem->completion); | 1354 | complete(&devmem->completion); |
| 1355 | } | 1355 | } |
| 1356 | 1356 | ||
| 1357 | static void hmm_devmem_ref_exit(void *data) | 1357 | static void hmm_devmem_ref_exit(struct percpu_ref *ref) |
| 1358 | { | 1358 | { |
| 1359 | struct percpu_ref *ref = data; | ||
| 1360 | struct hmm_devmem *devmem; | 1359 | struct hmm_devmem *devmem; |
| 1361 | 1360 | ||
| 1362 | devmem = container_of(ref, struct hmm_devmem, ref); | 1361 | devmem = container_of(ref, struct hmm_devmem, ref); |
| @@ -1433,10 +1432,6 @@ struct hmm_devmem *hmm_devmem_add(const struct hmm_devmem_ops *ops, · 70 unmodified lines | |||
| 1433 | if (ret) | 1432 | if (ret) |
| 1434 | return ERR_PTR(ret); | 1433 | return ERR_PTR(ret); |
| 1435 | 1434 | ||
| 1436 | ret = devm_add_action_or_reset(device, hmm_devmem_ref_exit, &devmem->ref); | ||
| 1437 | if (ret) | ||
| 1438 | return ERR_PTR(ret); | ||
| 1439 | |||
| 1440 | size = ALIGN(size, PA_SECTION_SIZE); | 1435 | size = ALIGN(size, PA_SECTION_SIZE); |
| 1441 | addr = min((unsigned long)iomem_resource.end, | 1436 | addr = min((unsigned long)iomem_resource.end, |
| 1442 | (1UL << MAX_PHYSMEM_BITS) - 1); | 1437 | (1UL << MAX_PHYSMEM_BITS) - 1); |
| @@ -1475,6 +1470,7 @@ struct hmm_devmem *hmm_devmem_add(const struct hmm_devmem_ops *ops, · 32 unmodified lines | |||
| 1475 | devmem->pagemap.ref = &devmem->ref; | 1470 | devmem->pagemap.ref = &devmem->ref; |
| 1476 | devmem->pagemap.data = devmem; | 1471 | devmem->pagemap.data = devmem; |
| 1477 | devmem->pagemap.kill = hmm_devmem_ref_kill; | 1472 | devmem->pagemap.kill = hmm_devmem_ref_kill; |
| 1473 | devmem->pagemap.cleanup = hmm_devmem_ref_exit; | ||
| 1478 | 1474 | ||
| 1479 | result = devm_memremap_pages(devmem->device, &devmem->pagemap); | 1475 | result = devm_memremap_pages(devmem->device, &devmem->pagemap); |
| 1480 | if (IS_ERR(result)) | 1476 | if (IS_ERR(result)) |
| @@ -1512,11 +1508,6 @@ struct hmm_devmem *hmm_devmem_add_resource(const struct hmm_devmem_ops *ops, · 31 unmodified lines | |||
| 1512 | if (ret) | 1508 | if (ret) |
| 1513 | return ERR_PTR(ret); | 1509 | return ERR_PTR(ret); |
| 1514 | 1510 | ||
| 1515 | ret = devm_add_action_or_reset(device, hmm_devmem_ref_exit, | ||
| 1516 | &devmem->ref); | ||
| 1517 | if (ret) | ||
| 1518 | return ERR_PTR(ret); | ||
| 1519 | |||
| 1520 | devmem->pfn_first = devmem->resource->start >> PAGE_SHIFT; | 1511 | devmem->pfn_first = devmem->resource->start >> PAGE_SHIFT; |
| 1521 | devmem->pfn_last = devmem->pfn_first + | 1512 | devmem->pfn_last = devmem->pfn_first + |
| 1522 | (resource_size(devmem->resource) >> PAGE_SHIFT); | 1513 | (resource_size(devmem->resource) >> PAGE_SHIFT); |
| @@ -1529,6 +1520,7 @@ struct hmm_devmem *hmm_devmem_add_resource(const struct hmm_devmem_ops *ops, · 6 unmodified lines | |||
| 1529 | devmem->pagemap.ref = &devmem->ref; | 1520 | devmem->pagemap.ref = &devmem->ref; |
| 1530 | devmem->pagemap.data = devmem; | 1521 | devmem->pagemap.data = devmem; |
| 1531 | devmem->pagemap.kill = hmm_devmem_ref_kill; | 1522 | devmem->pagemap.kill = hmm_devmem_ref_kill; |
| 1523 | devmem->pagemap.cleanup = hmm_devmem_ref_exit; | ||
| 1532 | 1524 | ||
| 1533 | result = devm_memremap_pages(devmem->device, &devmem->pagemap); | 1525 | result = devm_memremap_pages(devmem->device, &devmem->pagemap); |
| 1534 | if (IS_ERR(result)) | 1526 | if (IS_ERR(result)) |
| @@ -1004,6 +1004,9 @@ static void collapse_huge_page(struct mm_struct *mm, · 1003 unmodified lines | |||
| 1004 | * handled by the anon_vma lock + PG_lock. | 1004 | * handled by the anon_vma lock + PG_lock. |
| 1005 | */ | 1005 | */ |
| 1006 | down_write(&mm->mmap_sem); | 1006 | down_write(&mm->mmap_sem); |
| 1007 | result = SCAN_ANY_PROCESS; | ||
| 1008 | if (!mmget_still_valid(mm)) | ||
| 1009 | goto out; | ||
| 1007 | result = hugepage_vma_revalidate(mm, address, &vma); | 1010 | result = hugepage_vma_revalidate(mm, address, &vma); |
| 1008 | if (result) | 1011 | if (result) |
| 1009 | goto out; | 1012 | goto out; |
| @@ -354,7 +354,7 @@ static int __memcg_init_list_lru_node(struct list_lru_memcg *memcg_lrus, · 353 unmodified lines | |||
| 354 | } | 354 | } |
| 355 | return 0; | 355 | return 0; |
| 356 | fail: | 356 | fail: |
| 357 | __memcg_destroy_list_lru_node(memcg_lrus, begin, i - 1); | 357 | __memcg_destroy_list_lru_node(memcg_lrus, begin, i); |
| 358 | return -ENOMEM; | 358 | return -ENOMEM; |
| 359 | } | 359 | } |
| 360 | 360 | ||
| @@ -691,11 +691,12 @@ void __mod_memcg_state(struct mem_cgroup *memcg, int idx, int val) · 690 unmodified lines | |||
| 691 | if (mem_cgroup_disabled()) | 691 | if (mem_cgroup_disabled()) |
| 692 | return; | 692 | return; |
| 693 | 693 | ||
| 694 | __this_cpu_add(memcg->vmstats_local->stat[idx], val); | ||
| 695 | |||
| 694 | x = val + __this_cpu_read(memcg->vmstats_percpu->stat[idx]); | 696 | x = val + __this_cpu_read(memcg->vmstats_percpu->stat[idx]); |
| 695 | if (unlikely(abs(x) > MEMCG_CHARGE_BATCH)) { | 697 | if (unlikely(abs(x) > MEMCG_CHARGE_BATCH)) { |
| 696 | struct mem_cgroup *mi; | 698 | struct mem_cgroup *mi; |
| 697 | 699 | ||
| 698 | atomic_long_add(x, &memcg->vmstats_local[idx]); | ||
| 699 | for (mi = memcg; mi; mi = parent_mem_cgroup(mi)) | 700 | for (mi = memcg; mi; mi = parent_mem_cgroup(mi)) |
| 700 | atomic_long_add(x, &mi->vmstats[idx]); | 701 | atomic_long_add(x, &mi->vmstats[idx]); |
| 701 | x = 0; | 702 | x = 0; |
| @@ -745,11 +746,12 @@ void __mod_lruvec_state(struct lruvec *lruvec, enum node_stat_item idx, · 43 unmodified lines | |||
| 745 | __mod_memcg_state(memcg, idx, val); | 746 | __mod_memcg_state(memcg, idx, val); |
| 746 | 747 | ||
| 747 | /* Update lruvec */ | 748 | /* Update lruvec */ |
| 749 | __this_cpu_add(pn->lruvec_stat_local->count[idx], val); | ||
| 750 | |||
| 748 | x = val + __this_cpu_read(pn->lruvec_stat_cpu->count[idx]); | 751 | x = val + __this_cpu_read(pn->lruvec_stat_cpu->count[idx]); |
| 749 | if (unlikely(abs(x) > MEMCG_CHARGE_BATCH)) { | 752 | if (unlikely(abs(x) > MEMCG_CHARGE_BATCH)) { |
| 750 | struct mem_cgroup_per_node *pi; | 753 | struct mem_cgroup_per_node *pi; |
| 751 | 754 | ||
| 752 | atomic_long_add(x, &pn->lruvec_stat_local[idx]); | ||
| 753 | for (pi = pn; pi; pi = parent_nodeinfo(pi, pgdat->node_id)) | 755 | for (pi = pn; pi; pi = parent_nodeinfo(pi, pgdat->node_id)) |
| 754 | atomic_long_add(x, &pi->lruvec_stat[idx]); | 756 | atomic_long_add(x, &pi->lruvec_stat[idx]); |
| 755 | x = 0; | 757 | x = 0; |
| @@ -771,11 +773,12 @@ void __count_memcg_events(struct mem_cgroup *memcg, enum vm_event_item idx, · 15 unmodified lines | |||
| 771 | if (mem_cgroup_disabled()) | 773 | if (mem_cgroup_disabled()) |
| 772 | return; | 774 | return; |
| 773 | 775 | ||
| 776 | __this_cpu_add(memcg->vmstats_local->events[idx], count); | ||
| 777 | |||
| 774 | x = count + __this_cpu_read(memcg->vmstats_percpu->events[idx]); | 778 | x = count + __this_cpu_read(memcg->vmstats_percpu->events[idx]); |
| 775 | if (unlikely(x > MEMCG_CHARGE_BATCH)) { | 779 | if (unlikely(x > MEMCG_CHARGE_BATCH)) { |
| 776 | struct mem_cgroup *mi; | 780 | struct mem_cgroup *mi; |
| 777 | 781 | ||
| 778 | atomic_long_add(x, &memcg->vmevents_local[idx]); | ||
| 779 | for (mi = memcg; mi; mi = parent_mem_cgroup(mi)) | 782 | for (mi = memcg; mi; mi = parent_mem_cgroup(mi)) |
| 780 | atomic_long_add(x, &mi->vmevents[idx]); | 783 | atomic_long_add(x, &mi->vmevents[idx]); |
| 781 | x = 0; | 784 | x = 0; |
| @@ -790,7 +793,12 @@ static unsigned long memcg_events(struct mem_cgroup *memcg, int event) · 8 unmodified lines | |||
| 790 | 793 | ||
| 791 | static unsigned long memcg_events_local(struct mem_cgroup *memcg, int event) | 794 | static unsigned long memcg_events_local(struct mem_cgroup *memcg, int event) |
| 792 | { | 795 | { |
| 793 | return atomic_long_read(&memcg->vmevents_local[event]); | 796 | long x = 0; |
| 797 | int cpu; | ||
| 798 | |||
| 799 | for_each_possible_cpu(cpu) | ||
| 800 | x += per_cpu(memcg->vmstats_local->events[event], cpu); | ||
| 801 | return x; | ||
| 794 | } | 802 | } |
| 795 | 803 | ||
| 796 | static void mem_cgroup_charge_statistics(struct mem_cgroup *memcg, | 804 | static void mem_cgroup_charge_statistics(struct mem_cgroup *memcg, |
| @@ -2191,11 +2199,9 @@ static int memcg_hotplug_cpu_dead(unsigned int cpu) · 1394 unmodified lines | |||
| 2191 | long x; | 2199 | long x; |
| 2192 | 2200 | ||
| 2193 | x = this_cpu_xchg(memcg->vmstats_percpu->stat[i], 0); | 2201 | x = this_cpu_xchg(memcg->vmstats_percpu->stat[i], 0); |
| 2194 | if (x) { | 2202 | if (x) |
| 2195 | atomic_long_add(x, &memcg->vmstats_local[i]); | ||
| 2196 | for (mi = memcg; mi; mi = parent_mem_cgroup(mi)) | 2203 | for (mi = memcg; mi; mi = parent_mem_cgroup(mi)) |
| 2197 | atomic_long_add(x, &memcg->vmstats[i]); | 2204 | atomic_long_add(x, &memcg->vmstats[i]); |
| 2198 | } | ||
| 2199 | 2205 | ||
| 2200 | if (i >= NR_VM_NODE_STAT_ITEMS) | 2206 | if (i >= NR_VM_NODE_STAT_ITEMS) |
| 2201 | continue; | 2207 | continue; |
| @@ -2205,12 +2211,10 @@ static int memcg_hotplug_cpu_dead(unsigned int cpu) · 3 unmodified lines | |||
| 2205 | 2211 | ||
| 2206 | pn = mem_cgroup_nodeinfo(memcg, nid); | 2212 | pn = mem_cgroup_nodeinfo(memcg, nid); |
| 2207 | x = this_cpu_xchg(pn->lruvec_stat_cpu->count[i], 0); | 2213 | x = this_cpu_xchg(pn->lruvec_stat_cpu->count[i], 0); |
| 2208 | if (x) { | 2214 | if (x) |
| 2209 | atomic_long_add(x, &pn->lruvec_stat_local[i]); | ||
| 2210 | do { | 2215 | do { |
| 2211 | atomic_long_add(x, &pn->lruvec_stat[i]); | 2216 | atomic_long_add(x, &pn->lruvec_stat[i]); |
| 2212 | } while ((pn = parent_nodeinfo(pn, nid))); | 2217 | } while ((pn = parent_nodeinfo(pn, nid))); |
| 2213 | } | ||
| 2214 | } | 2218 | } |
| 2215 | } | 2219 | } |
| 2216 | 2220 | ||
| @@ -2218,11 +2222,9 @@ static int memcg_hotplug_cpu_dead(unsigned int cpu) · 1 unmodified line | |||
| 2218 | long x; | 2222 | long x; |
| 2219 | 2223 | ||
| 2220 | x = this_cpu_xchg(memcg->vmstats_percpu->events[i], 0); | 2224 | x = this_cpu_xchg(memcg->vmstats_percpu->events[i], 0); |
| 2221 | if (x) { | 2225 | if (x) |
| 2222 | atomic_long_add(x, &memcg->vmevents_local[i]); | ||
| 2223 | for (mi = memcg; mi; mi = parent_mem_cgroup(mi)) | 2226 | for (mi = memcg; mi; mi = parent_mem_cgroup(mi)) |
| 2224 | atomic_long_add(x, &memcg->vmevents[i]); | 2227 | atomic_long_add(x, &memcg->vmevents[i]); |
| 2225 | } | ||
| 2226 | } | 2228 | } |
| 2227 | } | 2229 | } |
| 2228 | 2230 | ||
| @@ -4483,8 +4485,15 @@ static int alloc_mem_cgroup_per_node_info(struct mem_cgroup *memcg, int node) · 2254 unmodified lines | |||
| 4483 | if (!pn) | 4485 | if (!pn) |
| 4484 | return 1; | 4486 | return 1; |
| 4485 | 4487 | ||
| 4488 | pn->lruvec_stat_local = alloc_percpu(struct lruvec_stat); | ||
| 4489 | if (!pn->lruvec_stat_local) { | ||
| 4490 | kfree(pn); | ||
| 4491 | return 1; | ||
| 4492 | } | ||
| 4493 | |||
| 4486 | pn->lruvec_stat_cpu = alloc_percpu(struct lruvec_stat); | 4494 | pn->lruvec_stat_cpu = alloc_percpu(struct lruvec_stat); |
| 4487 | if (!pn->lruvec_stat_cpu) { | 4495 | if (!pn->lruvec_stat_cpu) { |
| 4496 | free_percpu(pn->lruvec_stat_local); | ||
| 4488 | kfree(pn); | 4497 | kfree(pn); |
| 4489 | return 1; | 4498 | return 1; |
| 4490 | } | 4499 | } |
| @@ -4506,6 +4515,7 @@ static void free_mem_cgroup_per_node_info(struct mem_cgroup *memcg, int node) · 15 unmodified lines | |||
| 4506 | return; | 4515 | return; |
| 4507 | 4516 | ||
| 4508 | free_percpu(pn->lruvec_stat_cpu); | 4517 | free_percpu(pn->lruvec_stat_cpu); |
| 4518 | free_percpu(pn->lruvec_stat_local); | ||
| 4509 | kfree(pn); | 4519 | kfree(pn); |
| 4510 | } | 4520 | } |
| 4511 | 4521 | ||
| @@ -4516,6 +4526,7 @@ static void __mem_cgroup_free(struct mem_cgroup *memcg) · 4 unmodified lines | |||
| 4516 | for_each_node(node) | 4526 | for_each_node(node) |
| 4517 | free_mem_cgroup_per_node_info(memcg, node); | 4527 | free_mem_cgroup_per_node_info(memcg, node); |
| 4518 | free_percpu(memcg->vmstats_percpu); | 4528 | free_percpu(memcg->vmstats_percpu); |
| 4529 | free_percpu(memcg->vmstats_local); | ||
| 4519 | kfree(memcg); | 4530 | kfree(memcg); |
| 4520 | } | 4531 | } |
| 4521 | 4532 | ||
| @@ -4544,6 +4555,10 @@ static struct mem_cgroup *mem_cgroup_alloc(void) · 22 unmodified lines | |||
| 4544 | if (memcg->id.id < 0) | 4555 | if (memcg->id.id < 0) |
| 4545 | goto fail; | 4556 | goto fail; |
| 4546 | 4557 | ||
| 4558 | memcg->vmstats_local = alloc_percpu(struct memcg_vmstats_percpu); | ||
| 4559 | if (!memcg->vmstats_local) | ||
| 4560 | goto fail; | ||
| 4561 | |||
| 4547 | memcg->vmstats_percpu = alloc_percpu(struct memcg_vmstats_percpu); | 4562 | memcg->vmstats_percpu = alloc_percpu(struct memcg_vmstats_percpu); |
| 4548 | if (!memcg->vmstats_percpu) | 4563 | if (!memcg->vmstats_percpu) |
| 4549 | goto fail; | 4564 | goto fail; |
| @@ -636,11 +636,11 @@ static int apply_vma_lock_flags(unsigned long start, size_t len, · 635 unmodified lines | |||
| 636 | * is also counted. | 636 | * is also counted. |
| 637 | * Return value: previously mlocked page counts | 637 | * Return value: previously mlocked page counts |
| 638 | */ | 638 | */ |
| 639 | static int count_mm_mlocked_page_nr(struct mm_struct *mm, | 639 | static unsigned long count_mm_mlocked_page_nr(struct mm_struct *mm, |
| 640 | unsigned long start, size_t len) | 640 | unsigned long start, size_t len) |
| 641 | { | 641 | { |
| 642 | struct vm_area_struct *vma; | 642 | struct vm_area_struct *vma; |
| 643 | int count = 0; | 643 | unsigned long count = 0; |
| 644 | 644 | ||
| 645 | if (mm == NULL) | 645 | if (mm == NULL) |
| 646 | mm = current->mm; | 646 | mm = current->mm; |
| @@ -797,7 +797,8 @@ SYSCALL_DEFINE1(mlockall, int, flags) · 150 unmodified lines | |||
| 797 | unsigned long lock_limit; | 797 | unsigned long lock_limit; |
| 798 | int ret; | 798 | int ret; |
| 799 | 799 | ||
| 800 | if (!flags || (flags & ~(MCL_CURRENT | MCL_FUTURE | MCL_ONFAULT))) | 800 | if (!flags || (flags & ~(MCL_CURRENT | MCL_FUTURE | MCL_ONFAULT)) || |
| 801 | flags == MCL_ONFAULT) | ||
| 801 | return -EINVAL; | 802 | return -EINVAL; |
| 802 | 803 | ||
| 803 | if (!can_do_mlock()) | 804 | if (!can_do_mlock()) |
| @@ -245,14 +245,28 @@ void tlb_finish_mmu(struct mmu_gather *tlb, · 244 unmodified lines | |||
| 245 | { | 245 | { |
| 246 | /* | 246 | /* |
| 247 | * If there are parallel threads are doing PTE changes on same range | 247 | * If there are parallel threads are doing PTE changes on same range |
| 248 | * under non-exclusive lock(e.g., mmap_sem read-side) but defer TLB | 248 | * under non-exclusive lock (e.g., mmap_sem read-side) but defer TLB |
| 249 | * flush by batching, a thread has stable TLB entry can fail to flush | 249 | * flush by batching, one thread may end up seeing inconsistent PTEs |
| 250 | * the TLB by observing pte_none|!pte_dirty, for example so flush TLB | 250 | * and result in having stale TLB entries. So flush TLB forcefully |
| 251 | * forcefully if we detect parallel PTE batching threads. | 251 | * if we detect parallel PTE batching threads. |
| 252 | * | ||
| 253 | * However, some syscalls, e.g. munmap(), may free page tables, this | ||
| 254 | * needs force flush everything in the given range. Otherwise this | ||
| 255 | * may result in having stale TLB entries for some architectures, | ||
| 256 | * e.g. aarch64, that could specify flush what level TLB. | ||
| 252 | */ | 257 | */ |
| 253 | if (mm_tlb_flush_nested(tlb->mm)) { | 258 | if (mm_tlb_flush_nested(tlb->mm)) { |
| 259 | /* | ||
| 260 | * The aarch64 yields better performance with fullmm by | ||
| 261 | * avoiding multiple CPUs spamming TLBI messages at the | ||
| 262 | * same time. | ||
| 263 | * | ||
| 264 | * On x86 non-fullmm doesn't yield significant difference | ||
| 265 | * against fullmm. | ||
| 266 | */ | ||
| 267 | tlb->fullmm = 1; | ||
| 254 | __tlb_reset_range(tlb); | 268 | __tlb_reset_range(tlb); |
| 255 | __tlb_adjust_range(tlb, start, end - start); | 269 | tlb->freed_tables = 1; |
| 256 | } | 270 | } |
| 257 | 271 | ||
| 258 | tlb_flush_mmu(tlb); | 272 | tlb_flush_mmu(tlb); |
| @@ -1505,7 +1505,7 @@ unsigned long reclaim_clean_pages_from_list(struct zone *zone, · 1504 unmodified lines | |||
| 1505 | 1505 | ||
| 1506 | list_for_each_entry_safe(page, next, page_list, lru) { | 1506 | list_for_each_entry_safe(page, next, page_list, lru) { |
| 1507 | if (page_is_file_cache(page) && !PageDirty(page) && | 1507 | if (page_is_file_cache(page) && !PageDirty(page) && |
| 1508 | !__PageMovable(page)) { | 1508 | !__PageMovable(page) && !PageUnevictable(page)) { |
| 1509 | ClearPageActive(page); | 1509 | ClearPageActive(page); |
| 1510 | list_move(&page->lru, &clean_pages); | 1510 | list_move(&page->lru, &clean_pages); |
| 1511 | } | 1511 | } |
| @@ -1953,8 +1953,8 @@ shrink_inactive_list(unsigned long nr_to_scan, struct lruvec *lruvec, · 441 unmodified lines | |||
| 1953 | if (global_reclaim(sc)) | 1953 | if (global_reclaim(sc)) |
| 1954 | __count_vm_events(item, nr_reclaimed); | 1954 | __count_vm_events(item, nr_reclaimed); |
| 1955 | __count_memcg_events(lruvec_memcg(lruvec), item, nr_reclaimed); | 1955 | __count_memcg_events(lruvec_memcg(lruvec), item, nr_reclaimed); |
| 1956 | reclaim_stat->recent_rotated[0] = stat.nr_activate[0]; | 1956 | reclaim_stat->recent_rotated[0] += stat.nr_activate[0]; |
| 1957 | reclaim_stat->recent_rotated[1] = stat.nr_activate[1]; | 1957 | reclaim_stat->recent_rotated[1] += stat.nr_activate[1]; |
| 1958 | 1958 | ||
| 1959 | move_pages_to_lru(lruvec, &page_list); | 1959 | move_pages_to_lru(lruvec, &page_list); |
| 1960 | 1960 | ||
| @@ -73,7 +73,7 @@ parse_symbol() { · 72 unmodified lines | |||
| 73 | if [[ "${cache[$module,$address]+isset}" == "isset" ]]; then | 73 | if [[ "${cache[$module,$address]+isset}" == "isset" ]]; then |
| 74 | local code=${cache[$module,$address]} | 74 | local code=${cache[$module,$address]} |
| 75 | else | 75 | else |
| 76 | local code=$(addr2line -i -e "$objfile" "$address") | 76 | local code=$(${CROSS_COMPILE}addr2line -i -e "$objfile" "$address") |
| 77 | cache[$module,$address]=$code | 77 | cache[$module,$address]=$code |
| 78 | fi | 78 | fi |
| 79 | 79 | ||
| @@ -100,7 +100,9 @@ static void nfit_test_kill(void *_pgmap) · 99 unmodified lines | |||
| 100 | { | 100 | { |
| 101 | struct dev_pagemap *pgmap = _pgmap; | 101 | struct dev_pagemap *pgmap = _pgmap; |
| 102 | 102 | ||
| 103 | WARN_ON(!pgmap || !pgmap->ref || !pgmap->kill || !pgmap->cleanup); | ||
| 103 | pgmap->kill(pgmap->ref); | 104 | pgmap->kill(pgmap->ref); |
| 105 | pgmap->cleanup(pgmap->ref); | ||
| 104 | } | 106 | } |
| 105 | 107 | ||
| 106 | void *__wrap_devm_memremap_pages(struct device *dev, struct dev_pagemap *pgmap) | 108 | void *__wrap_devm_memremap_pages(struct device *dev, struct dev_pagemap *pgmap) |