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 | 756 | WARN_ON(devres_destroy(dev, devm_action_release, devm_action_match, |
| 757 | 757 | &devres)); |
| 758 | − | |
| 759 | 758 | } |
| 760 | 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 | 785 | * Managed kmalloc/kfree |
| 764 | 786 | */ |
| @@ -27,9 +27,8 @@ static void dev_dax_percpu_release(struct percpu_ref *ref) · 26 unmodified lines | ||
| 27 | 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 | 32 | struct dev_dax *dev_dax = ref_to_dev_dax(ref); |
| 34 | 33 | |
| 35 | 34 | dev_dbg(&dev_dax->dev, "%s\n", __func__); |
| @@ -466,18 +465,12 @@ int dev_dax_probe(struct device *dev) · 430 unmodified lines | ||
| 466 | 465 | if (rc) |
| 467 | 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 | 468 | dev_dax->pgmap.ref = &dev_dax->ref; |
| 474 | 469 | dev_dax->pgmap.kill = dev_dax_percpu_kill; |
| 470 | + dev_dax->pgmap.cleanup = dev_dax_percpu_exit; | |
| 475 | 471 | addr = devm_memremap_pages(dev, &dev_dax->pgmap); |
| 476 | − if (IS_ERR(addr)) { | |
| 477 | − devm_remove_action(dev, dev_dax_percpu_exit, &dev_dax->ref); | |
| 478 | − percpu_ref_exit(&dev_dax->ref); | |
| 472 | + if (IS_ERR(addr)) | |
| 479 | 473 | return PTR_ERR(addr); |
| 480 | − } | |
| 481 | 474 | |
| 482 | 475 | inode = dax_inode(dax_dev); |
| 483 | 476 | cdev = inode->i_cdev; |
| @@ -303,11 +303,19 @@ static const struct attribute_group *pmem_attribute_groups[] = { · 302 unmodified lines | ||
| 303 | 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 | 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 | 319 | static void pmem_freeze_queue(struct percpu_ref *ref) |
| 312 | 320 | { |
| 313 | 321 | struct request_queue *q; |
| @@ -399,12 +407,10 @@ static int pmem_attach_disk(struct device *dev, · 85 unmodified lines | ||
| 399 | 407 | if (!q) |
| 400 | 408 | return -ENOMEM; |
| 401 | 409 | |
| 402 | − if (devm_add_action_or_reset(dev, pmem_release_queue, q)) | |
| 403 | − return -ENOMEM; | |
| 404 | − | |
| 405 | 410 | pmem->pfn_flags = PFN_DEV; |
| 406 | 411 | pmem->pgmap.ref = &q->q_usage_counter; |
| 407 | 412 | pmem->pgmap.kill = pmem_freeze_queue; |
| 413 | + pmem->pgmap.cleanup = __pmem_release_queue; | |
| 408 | 414 | if (is_nd_pfn(dev)) { |
| 409 | 415 | if (setup_pagemap_fsdax(dev, &pmem->pgmap)) |
| 410 | 416 | return -ENOMEM; |
| @@ -425,6 +431,9 @@ static int pmem_attach_disk(struct device *dev, · 14 unmodified lines | ||
| 425 | 431 | pmem->pfn_flags |= PFN_MAP; |
| 426 | 432 | memcpy(&bb_res, &pmem->pgmap.res, sizeof(bb_res)); |
| 427 | 433 | } else { |
| 434 | + if (devm_add_action_or_reset(dev, pmem_release_queue, | |
| 435 | + &q->q_usage_counter)) | |
| 436 | + return -ENOMEM; | |
| 428 | 437 | addr = devm_memremap(dev, pmem->phys_addr, |
| 429 | 438 | pmem->size, ARCH_MEMREMAP_PMEM); |
| 430 | 439 | memcpy(&bb_res, &nsio->res, sizeof(bb_res)); |
| @@ -20,12 +20,16 @@ · 19 unmodified lines | ||
| 20 | 20 | #include <linux/seq_buf.h> |
| 21 | 21 | |
| 22 | 22 | struct pci_p2pdma { |
| 23 | − struct percpu_ref devmap_ref; | |
| 24 | − struct completion devmap_ref_done; | |
| 25 | 23 | struct gen_pool *pool; |
| 26 | 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 | 33 | static ssize_t size_show(struct device *dev, struct device_attribute *attr, |
| 30 | 34 | char *buf) |
| 31 | 35 | { |
| @@ -74,41 +78,45 @@ static const struct attribute_group p2pmem_group = { · 42 unmodified lines | ||
| 74 | 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 | 86 | static void pci_p2pdma_percpu_release(struct percpu_ref *ref) |
| 78 | 87 | { |
| 79 | − struct pci_p2pdma *p2p = | |
| 80 | − container_of(ref, struct pci_p2pdma, devmap_ref); | |
| 88 | + struct p2pdma_pagemap *p2p_pgmap = to_p2p_pgmap(ref); | |
| 81 | 89 | |
| 82 | − complete_all(&p2p->devmap_ref_done); | |
| 90 | + complete(&p2p_pgmap->ref_done); | |
| 83 | 91 | } |
| 84 | 92 | |
| 85 | 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 | 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 | 106 | static void pci_p2pdma_release(void *data) |
| 100 | 107 | { |
| 101 | 108 | struct pci_dev *pdev = data; |
| 109 | + struct pci_p2pdma *p2pdma = pdev->p2pdma; | |
| 102 | 110 | |
| 103 | − if (!pdev->p2pdma) | |
| 111 | + if (!p2pdma) | |
| 104 | 112 | return; |
| 105 | 113 | |
| 106 | − wait_for_completion(&pdev->p2pdma->devmap_ref_done); | |
| 107 | − percpu_ref_exit(&pdev->p2pdma->devmap_ref); | |
| 114 | + /* Flush and disable pci_alloc_p2p_mem() */ | |
| 115 | + pdev->p2pdma = NULL; | |
| 116 | + synchronize_rcu(); | |
| 108 | 117 | |
| 109 | − gen_pool_destroy(pdev->p2pdma->pool); | |
| 118 | + gen_pool_destroy(p2pdma->pool); | |
| 110 | 119 | sysfs_remove_group(&pdev->dev.kobj, &p2pmem_group); |
| 111 | − pdev->p2pdma = NULL; | |
| 112 | 120 | } |
| 113 | 121 | |
| 114 | 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 | 132 | if (!p2p->pool) |
| 125 | 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 | 135 | error = devm_add_action_or_reset(&pdev->dev, pci_p2pdma_release, pdev); |
| 134 | 136 | if (error) |
| 135 | 137 | goto out_pool_destroy; |
| @@ -163,6 +165,7 @@ out: · 27 unmodified lines | ||
| 163 | 165 | int pci_p2pdma_add_resource(struct pci_dev *pdev, int bar, size_t size, |
| 164 | 166 | u64 offset) |
| 165 | 167 | { |
| 168 | + struct p2pdma_pagemap *p2p_pgmap; | |
| 166 | 169 | struct dev_pagemap *pgmap; |
| 167 | 170 | void *addr; |
| 168 | 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 | 188 | return error; |
| 186 | 189 | } |
| 187 | 190 | |
| 188 | − pgmap = devm_kzalloc(&pdev->dev, sizeof(*pgmap), GFP_KERNEL); | |
| 189 | − if (!pgmap) | |
| 191 | + p2p_pgmap = devm_kzalloc(&pdev->dev, sizeof(*p2p_pgmap), GFP_KERNEL); | |
| 192 | + if (!p2p_pgmap) | |
| 190 | 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 | 203 | pgmap->res.start = pci_resource_start(pdev, bar) + offset; |
| 193 | 204 | pgmap->res.end = pgmap->res.start + size - 1; |
| 194 | 205 | pgmap->res.flags = pci_resource_flags(pdev, bar); |
| 195 | − pgmap->ref = &pdev->p2pdma->devmap_ref; | |
| 206 | + pgmap->ref = &p2p_pgmap->ref; | |
| 196 | 207 | pgmap->type = MEMORY_DEVICE_PCI_P2PDMA; |
| 197 | 208 | pgmap->pci_p2pdma_bus_offset = pci_bus_address(pdev, bar) - |
| 198 | 209 | pci_resource_start(pdev, bar); |
| 199 | 210 | pgmap->kill = pci_p2pdma_percpu_kill; |
| 211 | + pgmap->cleanup = pci_p2pdma_percpu_cleanup; | |
| 200 | 212 | |
| 201 | 213 | addr = devm_memremap_pages(&pdev->dev, pgmap); |
| 202 | 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 | 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 | 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 | 223 | if (error) |
| 211 | − goto pgmap_free; | |
| 224 | + goto pages_free; | |
| 212 | 225 | |
| 213 | 226 | pci_info(pdev, "added peer-to-peer DMA memory %pR\n", |
| 214 | 227 | &pgmap->res); |
| 215 | 228 | |
| 216 | 229 | return 0; |
| 217 | 230 | |
| 231 | +pages_free: | |
| 232 | + devm_memunmap_pages(&pdev->dev, pgmap); | |
| 218 | 233 | pgmap_free: |
| 219 | − devm_kfree(&pdev->dev, pgmap); | |
| 234 | + devm_kfree(&pdev->dev, p2p_pgmap); | |
| 220 | 235 | return error; |
| 221 | 236 | } |
| 222 | 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 | 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 | 612 | if (unlikely(!pdev->p2pdma)) |
| 591 | − return NULL; | |
| 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); | |
| 613 | + goto out; | |
| 597 | 614 | |
| 598 | − if (unlikely(!ret)) | |
| 599 | − percpu_ref_put(&pdev->p2pdma->devmap_ref); | |
| 615 | + ret = (void *)gen_pool_alloc_owner(pdev->p2pdma->pool, size, | |
| 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 | 627 | return ret; |
| 602 | 628 | } |
| 603 | 629 | EXPORT_SYMBOL_GPL(pci_alloc_p2pmem); |
| @@ -610,8 +636,11 @@ EXPORT_SYMBOL_GPL(pci_alloc_p2pmem); · 6 unmodified lines | ||
| 610 | 636 | */ |
| 611 | 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); | |
| 614 | − percpu_ref_put(&pdev->p2pdma->devmap_ref); | |
| 639 | + struct percpu_ref *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 | 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 | 297 | out_attach: |
| 298 | 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 | 311 | dentry->d_fsdata = dl; |
| 300 | 312 | dl->dl_count++; |
| 301 | 313 | spin_unlock(&dentry_attach_lock); |
| @@ -713,6 +713,7 @@ void __iomem *devm_of_iomap(struct device *dev, · 712 unmodified lines | ||
| 713 | 713 | /* allows to add/remove a custom action to devres stack */ |
| 714 | 714 | int devm_add_action(struct device *dev, void (*action)(void *), void *data); |
| 715 | 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 | 718 | static inline int devm_add_action_or_reset(struct device *dev, |
| 718 | 719 | void (*action)(void *), void *data) |
| @@ -75,6 +75,7 @@ struct gen_pool_chunk { · 74 unmodified lines | ||
| 75 | 75 | struct list_head next_chunk; /* next chunk in pool */ |
| 76 | 76 | atomic_long_t avail; |
| 77 | 77 | phys_addr_t phys_addr; /* physical starting address of memory chunk */ |
| 78 | + void *owner; /* private data to retrieve at alloc time */ | |
| 78 | 79 | unsigned long start_addr; /* start address of memory chunk */ |
| 79 | 80 | unsigned long end_addr; /* end address of memory chunk (inclusive) */ |
| 80 | 81 | unsigned long bits[0]; /* bitmap for allocating memory chunk */ |
| @@ -96,8 +97,15 @@ struct genpool_data_fixed { · 15 unmodified lines | ||
| 96 | 97 | |
| 97 | 98 | extern struct gen_pool *gen_pool_create(int, int); |
| 98 | 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 | − size_t, int); | |
| 100 | +extern int gen_pool_add_owner(struct gen_pool *, unsigned long, phys_addr_t, | |
| 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 | 110 | * gen_pool_add - add a new chunk of special memory to the pool |
| 103 | 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 | 124 | return gen_pool_add_virt(pool, addr, -1, size, nid); |
| 117 | 125 | } |
| 118 | 126 | extern void gen_pool_destroy(struct gen_pool *); |
| 119 | −extern unsigned long gen_pool_alloc(struct gen_pool *, size_t); | |
| 120 | −extern unsigned long gen_pool_alloc_algo(struct gen_pool *, size_t, | |
| 121 | − genpool_algo_t algo, void *data); | |
| 127 | +unsigned long gen_pool_alloc_algo_owner(struct gen_pool *pool, size_t size, | |
| 128 | + genpool_algo_t algo, void *data, void **owner); | |
| 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 | 158 | extern void *gen_pool_dma_alloc(struct gen_pool *pool, size_t size, |
| 123 | 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 | 168 | extern void gen_pool_for_each_chunk(struct gen_pool *, |
| 126 | 169 | void (*)(struct gen_pool *, struct gen_pool_chunk *, void *), void *); |
| 127 | 170 | extern size_t gen_pool_avail(struct gen_pool *); |
| @@ -117,9 +117,12 @@ struct memcg_shrinker_map { · 116 unmodified lines | ||
| 117 | 117 | struct mem_cgroup_per_node { |
| 118 | 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 | 124 | struct lruvec_stat __percpu *lruvec_stat_cpu; |
| 121 | 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 | 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 | 268 | atomic_t moving_account; |
| 266 | 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 | 275 | struct memcg_vmstats_percpu __percpu *vmstats_percpu; |
| 270 | 276 | |
| 271 | 277 | MEMCG_PADDING(_pad2_); |
| 272 | 278 | |
| 273 | 279 | atomic_long_t vmstats[MEMCG_NR_STAT]; |
| 274 | − atomic_long_t vmstats_local[MEMCG_NR_STAT]; | |
| 275 | − | |
| 276 | 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 | 283 | atomic_long_t memory_events[MEMCG_NR_MEMORY_EVENTS]; |
| 280 | 284 | |
| 281 | 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 | 571 | static inline unsigned long memcg_page_state_local(struct mem_cgroup *memcg, |
| 568 | 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 | 579 | #ifdef CONFIG_SMP |
| 572 | 580 | if (x < 0) |
| 573 | 581 | x = 0; |
| @@ -641,13 +649,15 @@ static inline unsigned long lruvec_page_state_local(struct lruvec *lruvec, · 67 unmodified lines | ||
| 641 | 649 | enum node_stat_item idx) |
| 642 | 650 | { |
| 643 | 651 | struct mem_cgroup_per_node *pn; |
| 644 | − long x; | |
| 652 | + long x = 0; | |
| 653 | + int cpu; | |
| 645 | 654 | |
| 646 | 655 | if (mem_cgroup_disabled()) |
| 647 | 656 | return node_page_state(lruvec_pgdat(lruvec), idx); |
| 648 | 657 | |
| 649 | 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 | 661 | #ifdef CONFIG_SMP |
| 652 | 662 | if (x < 0) |
| 653 | 663 | x = 0; |
| @@ -81,6 +81,7 @@ typedef void (*dev_page_free_t)(struct page *page, void *data); · 80 unmodified lines | ||
| 81 | 81 | * @res: physical address range covered by @ref |
| 82 | 82 | * @ref: reference count that pins the devm_memremap_pages() mapping |
| 83 | 83 | * @kill: callback to transition @ref to the dead state |
| 84 | + * @cleanup: callback to wait for @ref to be idle and reap it | |
| 84 | 85 | * @dev: host device of the mapping for debug |
| 85 | 86 | * @data: private data pointer for page_free() |
| 86 | 87 | * @type: memory type: see MEMORY_* in memory_hotplug.h |
| @@ -92,6 +93,7 @@ struct dev_pagemap { · 5 unmodified lines | ||
| 92 | 93 | struct resource res; |
| 93 | 94 | struct percpu_ref *ref; |
| 94 | 95 | void (*kill)(struct percpu_ref *ref); |
| 96 | + void (*cleanup)(struct percpu_ref *ref); | |
| 95 | 97 | struct device *dev; |
| 96 | 98 | void *data; |
| 97 | 99 | enum memory_type type; |
| @@ -100,6 +102,7 @@ struct dev_pagemap { · 2 unmodified lines | ||
| 100 | 102 | |
| 101 | 103 | #ifdef CONFIG_ZONE_DEVICE |
| 102 | 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 | 106 | struct dev_pagemap *get_dev_pagemap(unsigned long pfn, |
| 104 | 107 | struct dev_pagemap *pgmap); |
| 105 | 108 | |
| @@ -118,6 +121,11 @@ static inline void *devm_memremap_pages(struct device *dev, · 12 unmodified lines | ||
| 118 | 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 | 129 | static inline struct dev_pagemap *get_dev_pagemap(unsigned long pfn, |
| 122 | 130 | struct dev_pagemap *pgmap) |
| 123 | 131 | { |
| @@ -54,6 +54,10 @@ static inline void mmdrop(struct mm_struct *mm) · 53 unmodified lines | ||
| 54 | 54 | * followed by taking the mmap_sem for writing before modifying the |
| 55 | 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 | 61 | * NOTE: find_extend_vma() called from GUP context is the only place |
| 58 | 62 | * that can modify the "mm" (notably the vm_start/end) under mmap_sem |
| 59 | 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 | 95 | pgmap->kill(pgmap->ref); |
| 96 | 96 | for_each_device_pfn(pfn, pgmap) |
| 97 | 97 | put_page(pfn_to_page(pfn)); |
| 98 | + pgmap->cleanup(pgmap->ref); | |
| 98 | 99 | |
| 99 | 100 | /* pages are dead and unused, undo the arch mapping */ |
| 100 | 101 | align_start = res->start & ~(SECTION_SIZE - 1); |
| @@ -133,8 +134,8 @@ static void devm_memremap_pages_release(void *data) · 32 unmodified lines | ||
| 133 | 134 | * 2/ The altmap field may optionally be initialized, in which case altmap_valid |
| 134 | 135 | * must be set to true |
| 135 | 136 | * |
| 136 | − * 3/ pgmap->ref must be 'live' on entry and will be killed at | |
| 137 | − * devm_memremap_pages_release() time, or if this routine fails. | |
| 137 | + * 3/ pgmap->ref must be 'live' on entry and will be killed and reaped | |
| 138 | + * at devm_memremap_pages_release() time, or if this routine fails. | |
| 138 | 139 | * |
| 139 | 140 | * 4/ res is expected to be a host memory range that could feasibly be |
| 140 | 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 | 157 | pgprot_t pgprot = PAGE_KERNEL; |
| 157 | 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 | 162 | return ERR_PTR(-EINVAL); |
| 163 | + } | |
| 161 | 164 | |
| 162 | 165 | align_start = res->start & ~(SECTION_SIZE - 1); |
| 163 | 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 | 171 | if (conflict_pgmap) { |
| 169 | 172 | dev_WARN(dev, "Conflicting mapping in same section\n"); |
| 170 | 173 | put_dev_pagemap(conflict_pgmap); |
| 171 | − return ERR_PTR(-ENOMEM); | |
| 174 | + error = -ENOMEM; | |
| 175 | + goto err_array; | |
| 172 | 176 | } |
| 173 | 177 | |
| 174 | 178 | conflict_pgmap = get_dev_pagemap(PHYS_PFN(align_end), NULL); |
| 175 | 179 | if (conflict_pgmap) { |
| 176 | 180 | dev_WARN(dev, "Conflicting mapping in same section\n"); |
| 177 | 181 | put_dev_pagemap(conflict_pgmap); |
| 178 | − return ERR_PTR(-ENOMEM); | |
| 182 | + error = -ENOMEM; | |
| 183 | + goto err_array; | |
| 179 | 184 | } |
| 180 | 185 | |
| 181 | 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 | 272 | pgmap_array_delete(res); |
| 268 | 273 | err_array: |
| 269 | 274 | pgmap->kill(pgmap->ref); |
| 275 | + pgmap->cleanup(pgmap->ref); | |
| 276 | + | |
| 270 | 277 | return ERR_PTR(error); |
| 271 | 278 | } |
| 272 | 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 | 287 | unsigned long vmem_altmap_offset(struct vmem_altmap *altmap) |
| 275 | 288 | { |
| 276 | 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 | 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 | 172 | * @pool: pool to add new memory chunk to |
| 173 | 173 | * @virt: virtual starting address of memory chunk to add to pool |
| 174 | 174 | * @phys: physical starting address of memory chunk to add to pool |
| 175 | 175 | * @size: size in bytes of the memory chunk to add to pool |
| 176 | 176 | * @nid: node id of the node the chunk structure and bitmap should be |
| 177 | 177 | * allocated on, or -1 |
| 178 | + * @owner: private data the publisher would like to recall at alloc time | |
| 178 | 179 | * |
| 179 | 180 | * Add a new chunk of special memory to the specified pool. |
| 180 | 181 | * |
| 181 | 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 | − size_t size, int nid) | |
| 184 | +int gen_pool_add_owner(struct gen_pool *pool, unsigned long virt, phys_addr_t phys, | |
| 185 | + size_t size, int nid, void *owner) | |
| 185 | 186 | { |
| 186 | 187 | struct gen_pool_chunk *chunk; |
| 187 | 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 | 196 | chunk->phys_addr = phys; |
| 196 | 197 | chunk->start_addr = virt; |
| 197 | 198 | chunk->end_addr = virt + size - 1; |
| 199 | + chunk->owner = owner; | |
| 198 | 200 | atomic_long_set(&chunk->avail, size); |
| 199 | 201 | |
| 200 | 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 | 206 | return 0; |
| 205 | 207 | } |
| 206 | −EXPORT_SYMBOL(gen_pool_add_virt); | |
| 208 | +EXPORT_SYMBOL(gen_pool_add_owner); | |
| 207 | 209 | |
| 208 | 210 | /** |
| 209 | 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 | 262 | EXPORT_SYMBOL(gen_pool_destroy); |
| 261 | 263 | |
| 262 | 264 | /** |
| 263 | − * gen_pool_alloc - 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 | |
| 265 | + * gen_pool_alloc_algo_owner - allocate special memory from the pool | |
| 280 | 266 | * @pool: pool to allocate from |
| 281 | 267 | * @size: number of bytes to allocate from the pool |
| 282 | 268 | * @algo: algorithm passed from caller |
| 283 | 269 | * @data: data passed to algorithm |
| 270 | + * @owner: optionally retrieve the chunk owner | |
| 284 | 271 | * |
| 285 | 272 | * Allocate the requested number of bytes from the specified pool. |
| 286 | 273 | * Uses the pool allocation function (with first-fit algorithm by default). |
| 287 | 274 | * Can not be used in NMI handler on architectures without |
| 288 | 275 | * NMI-safe cmpxchg implementation. |
| 289 | 276 | */ |
| 290 | −unsigned long gen_pool_alloc_algo(struct gen_pool *pool, size_t size, | |
| 291 | − genpool_algo_t algo, void *data) | |
| 277 | +unsigned long gen_pool_alloc_algo_owner(struct gen_pool *pool, size_t size, | |
| 278 | + genpool_algo_t algo, void *data, void **owner) | |
| 292 | 279 | { |
| 293 | 280 | struct gen_pool_chunk *chunk; |
| 294 | 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 | 286 | BUG_ON(in_nmi()); |
| 300 | 287 | #endif |
| 301 | 288 | |
| 289 | + if (owner) | |
| 290 | + *owner = NULL; | |
| 291 | + | |
| 302 | 292 | if (size == 0) |
| 303 | 293 | return 0; |
| 304 | 294 | |
| @@ -326,12 +316,14 @@ retry: · 21 unmodified lines | ||
| 326 | 316 | addr = chunk->start_addr + ((unsigned long)start_bit << order); |
| 327 | 317 | size = nbits << order; |
| 328 | 318 | atomic_long_sub(size, &chunk->avail); |
| 319 | + if (owner) | |
| 320 | + *owner = chunk->owner; | |
| 329 | 321 | break; |
| 330 | 322 | } |
| 331 | 323 | rcu_read_unlock(); |
| 332 | 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 | 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 | 359 | * @pool: pool to free to |
| 368 | 360 | * @addr: starting address of memory to free back to pool |
| 369 | 361 | * @size: size in bytes of memory to free |
| 362 | + * @owner: private data stashed at gen_pool_add() time | |
| 370 | 363 | * |
| 371 | 364 | * Free previously allocated special memory back to the specified |
| 372 | 365 | * pool. Can not be used in NMI handler on architectures without |
| 373 | 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 | 371 | struct gen_pool_chunk *chunk; |
| 378 | 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 | 376 | BUG_ON(in_nmi()); |
| 383 | 377 | #endif |
| 384 | 378 | |
| 379 | + if (owner) | |
| 380 | + *owner = NULL; | |
| 381 | + | |
| 385 | 382 | nbits = (size + (1UL << order) - 1) >> order; |
| 386 | 383 | rcu_read_lock(); |
| 387 | 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 | 389 | BUG_ON(remain); |
| 393 | 390 | size = nbits << order; |
| 394 | 391 | atomic_long_add(size, &chunk->avail); |
| 392 | + if (owner) | |
| 393 | + *owner = chunk->owner; | |
| 395 | 394 | rcu_read_unlock(); |
| 396 | 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 | 398 | rcu_read_unlock(); |
| 400 | 399 | BUG(); |
| 401 | 400 | } |
| 402 | −EXPORT_SYMBOL(gen_pool_free); | |
| 401 | +EXPORT_SYMBOL(gen_pool_free_owner); | |
| 403 | 402 | |
| 404 | 403 | /** |
| 405 | 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 | 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 | 1359 | struct hmm_devmem *devmem; |
| 1361 | 1360 | |
| 1362 | 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 | 1432 | if (ret) |
| 1434 | 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 | 1435 | size = ALIGN(size, PA_SECTION_SIZE); |
| 1441 | 1436 | addr = min((unsigned long)iomem_resource.end, |
| 1442 | 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 | 1470 | devmem->pagemap.ref = &devmem->ref; |
| 1476 | 1471 | devmem->pagemap.data = devmem; |
| 1477 | 1472 | devmem->pagemap.kill = hmm_devmem_ref_kill; |
| 1473 | + devmem->pagemap.cleanup = hmm_devmem_ref_exit; | |
| 1478 | 1474 | |
| 1479 | 1475 | result = devm_memremap_pages(devmem->device, &devmem->pagemap); |
| 1480 | 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 | 1508 | if (ret) |
| 1513 | 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 | 1511 | devmem->pfn_first = devmem->resource->start >> PAGE_SHIFT; |
| 1521 | 1512 | devmem->pfn_last = devmem->pfn_first + |
| 1522 | 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 | 1520 | devmem->pagemap.ref = &devmem->ref; |
| 1530 | 1521 | devmem->pagemap.data = devmem; |
| 1531 | 1522 | devmem->pagemap.kill = hmm_devmem_ref_kill; |
| 1523 | + devmem->pagemap.cleanup = hmm_devmem_ref_exit; | |
| 1532 | 1524 | |
| 1533 | 1525 | result = devm_memremap_pages(devmem->device, &devmem->pagemap); |
| 1534 | 1526 | if (IS_ERR(result)) |
| @@ -1004,6 +1004,9 @@ static void collapse_huge_page(struct mm_struct *mm, · 1003 unmodified lines | ||
| 1004 | 1004 | * handled by the anon_vma lock + PG_lock. |
| 1005 | 1005 | */ |
| 1006 | 1006 | down_write(&mm->mmap_sem); |
| 1007 | + result = SCAN_ANY_PROCESS; | |
| 1008 | + if (!mmget_still_valid(mm)) | |
| 1009 | + goto out; | |
| 1007 | 1010 | result = hugepage_vma_revalidate(mm, address, &vma); |
| 1008 | 1011 | if (result) |
| 1009 | 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 | 355 | return 0; |
| 356 | 356 | fail: |
| 357 | − __memcg_destroy_list_lru_node(memcg_lrus, begin, i - 1); | |
| 357 | + __memcg_destroy_list_lru_node(memcg_lrus, begin, i); | |
| 358 | 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 | 691 | if (mem_cgroup_disabled()) |
| 692 | 692 | return; |
| 693 | 693 | |
| 694 | + __this_cpu_add(memcg->vmstats_local->stat[idx], val); | |
| 695 | + | |
| 694 | 696 | x = val + __this_cpu_read(memcg->vmstats_percpu->stat[idx]); |
| 695 | 697 | if (unlikely(abs(x) > MEMCG_CHARGE_BATCH)) { |
| 696 | 698 | struct mem_cgroup *mi; |
| 697 | 699 | |
| 698 | − atomic_long_add(x, &memcg->vmstats_local[idx]); | |
| 699 | 700 | for (mi = memcg; mi; mi = parent_mem_cgroup(mi)) |
| 700 | 701 | atomic_long_add(x, &mi->vmstats[idx]); |
| 701 | 702 | x = 0; |
| @@ -745,11 +746,12 @@ void __mod_lruvec_state(struct lruvec *lruvec, enum node_stat_item idx, · 43 unmodified lines | ||
| 745 | 746 | __mod_memcg_state(memcg, idx, val); |
| 746 | 747 | |
| 747 | 748 | /* Update lruvec */ |
| 749 | + __this_cpu_add(pn->lruvec_stat_local->count[idx], val); | |
| 750 | + | |
| 748 | 751 | x = val + __this_cpu_read(pn->lruvec_stat_cpu->count[idx]); |
| 749 | 752 | if (unlikely(abs(x) > MEMCG_CHARGE_BATCH)) { |
| 750 | 753 | struct mem_cgroup_per_node *pi; |
| 751 | 754 | |
| 752 | − atomic_long_add(x, &pn->lruvec_stat_local[idx]); | |
| 753 | 755 | for (pi = pn; pi; pi = parent_nodeinfo(pi, pgdat->node_id)) |
| 754 | 756 | atomic_long_add(x, &pi->lruvec_stat[idx]); |
| 755 | 757 | x = 0; |
| @@ -771,11 +773,12 @@ void __count_memcg_events(struct mem_cgroup *memcg, enum vm_event_item idx, · 15 unmodified lines | ||
| 771 | 773 | if (mem_cgroup_disabled()) |
| 772 | 774 | return; |
| 773 | 775 | |
| 776 | + __this_cpu_add(memcg->vmstats_local->events[idx], count); | |
| 777 | + | |
| 774 | 778 | x = count + __this_cpu_read(memcg->vmstats_percpu->events[idx]); |
| 775 | 779 | if (unlikely(x > MEMCG_CHARGE_BATCH)) { |
| 776 | 780 | struct mem_cgroup *mi; |
| 777 | 781 | |
| 778 | − atomic_long_add(x, &memcg->vmevents_local[idx]); | |
| 779 | 782 | for (mi = memcg; mi; mi = parent_mem_cgroup(mi)) |
| 780 | 783 | atomic_long_add(x, &mi->vmevents[idx]); |
| 781 | 784 | x = 0; |
| @@ -790,7 +793,12 @@ static unsigned long memcg_events(struct mem_cgroup *memcg, int event) · 8 unmodified lines | ||
| 790 | 793 | |
| 791 | 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 | 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 | 2199 | long x; |
| 2192 | 2200 | |
| 2193 | 2201 | x = this_cpu_xchg(memcg->vmstats_percpu->stat[i], 0); |
| 2194 | − if (x) { | |
| 2195 | − atomic_long_add(x, &memcg->vmstats_local[i]); | |
| 2202 | + if (x) | |
| 2196 | 2203 | for (mi = memcg; mi; mi = parent_mem_cgroup(mi)) |
| 2197 | 2204 | atomic_long_add(x, &memcg->vmstats[i]); |
| 2198 | − } | |
| 2199 | 2205 | |
| 2200 | 2206 | if (i >= NR_VM_NODE_STAT_ITEMS) |
| 2201 | 2207 | continue; |
| @@ -2205,12 +2211,10 @@ static int memcg_hotplug_cpu_dead(unsigned int cpu) · 3 unmodified lines | ||
| 2205 | 2211 | |
| 2206 | 2212 | pn = mem_cgroup_nodeinfo(memcg, nid); |
| 2207 | 2213 | x = this_cpu_xchg(pn->lruvec_stat_cpu->count[i], 0); |
| 2208 | − if (x) { | |
| 2209 | − atomic_long_add(x, &pn->lruvec_stat_local[i]); | |
| 2214 | + if (x) | |
| 2210 | 2215 | do { |
| 2211 | 2216 | atomic_long_add(x, &pn->lruvec_stat[i]); |
| 2212 | 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 | 2222 | long x; |
| 2219 | 2223 | |
| 2220 | 2224 | x = this_cpu_xchg(memcg->vmstats_percpu->events[i], 0); |
| 2221 | − if (x) { | |
| 2222 | − atomic_long_add(x, &memcg->vmevents_local[i]); | |
| 2225 | + if (x) | |
| 2223 | 2226 | for (mi = memcg; mi; mi = parent_mem_cgroup(mi)) |
| 2224 | 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 | 4485 | if (!pn) |
| 4484 | 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 | 4494 | pn->lruvec_stat_cpu = alloc_percpu(struct lruvec_stat); |
| 4487 | 4495 | if (!pn->lruvec_stat_cpu) { |
| 4496 | + free_percpu(pn->lruvec_stat_local); | |
| 4488 | 4497 | kfree(pn); |
| 4489 | 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 | 4515 | return; |
| 4507 | 4516 | |
| 4508 | 4517 | free_percpu(pn->lruvec_stat_cpu); |
| 4518 | + free_percpu(pn->lruvec_stat_local); | |
| 4509 | 4519 | kfree(pn); |
| 4510 | 4520 | } |
| 4511 | 4521 | |
| @@ -4516,6 +4526,7 @@ static void __mem_cgroup_free(struct mem_cgroup *memcg) · 4 unmodified lines | ||
| 4516 | 4526 | for_each_node(node) |
| 4517 | 4527 | free_mem_cgroup_per_node_info(memcg, node); |
| 4518 | 4528 | free_percpu(memcg->vmstats_percpu); |
| 4529 | + free_percpu(memcg->vmstats_local); | |
| 4519 | 4530 | kfree(memcg); |
| 4520 | 4531 | } |
| 4521 | 4532 | |
| @@ -4544,6 +4555,10 @@ static struct mem_cgroup *mem_cgroup_alloc(void) · 22 unmodified lines | ||
| 4544 | 4555 | if (memcg->id.id < 0) |
| 4545 | 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 | 4562 | memcg->vmstats_percpu = alloc_percpu(struct memcg_vmstats_percpu); |
| 4548 | 4563 | if (!memcg->vmstats_percpu) |
| 4549 | 4564 | goto fail; |
| @@ -636,11 +636,11 @@ static int apply_vma_lock_flags(unsigned long start, size_t len, · 635 unmodified lines | ||
| 636 | 636 | * is also counted. |
| 637 | 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 | 640 | unsigned long start, size_t len) |
| 641 | 641 | { |
| 642 | 642 | struct vm_area_struct *vma; |
| 643 | − int count = 0; | |
| 643 | + unsigned long count = 0; | |
| 644 | 644 | |
| 645 | 645 | if (mm == NULL) |
| 646 | 646 | mm = current->mm; |
| @@ -797,7 +797,8 @@ SYSCALL_DEFINE1(mlockall, int, flags) · 150 unmodified lines | ||
| 797 | 797 | unsigned long lock_limit; |
| 798 | 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 | 802 | return -EINVAL; |
| 802 | 803 | |
| 803 | 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 | 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 | |
| 249 | − * flush by batching, a thread has stable TLB entry can fail to flush | |
| 250 | − * the TLB by observing pte_none|!pte_dirty, for example so flush TLB | |
| 251 | − * forcefully if we detect parallel PTE batching threads. | |
| 248 | + * under non-exclusive lock (e.g., mmap_sem read-side) but defer TLB | |
| 249 | + * flush by batching, one thread may end up seeing inconsistent PTEs | |
| 250 | + * and result in having stale TLB entries. So flush TLB forcefully | |
| 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 | 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 | 268 | __tlb_reset_range(tlb); |
| 255 | − __tlb_adjust_range(tlb, start, end - start); | |
| 269 | + tlb->freed_tables = 1; | |
| 256 | 270 | } |
| 257 | 271 | |
| 258 | 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 | 1506 | list_for_each_entry_safe(page, next, page_list, lru) { |
| 1507 | 1507 | if (page_is_file_cache(page) && !PageDirty(page) && |
| 1508 | − !__PageMovable(page)) { | |
| 1508 | + !__PageMovable(page) && !PageUnevictable(page)) { | |
| 1509 | 1509 | ClearPageActive(page); |
| 1510 | 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 | 1953 | if (global_reclaim(sc)) |
| 1954 | 1954 | __count_vm_events(item, nr_reclaimed); |
| 1955 | 1955 | __count_memcg_events(lruvec_memcg(lruvec), item, nr_reclaimed); |
| 1956 | − reclaim_stat->recent_rotated[0] = stat.nr_activate[0]; | |
| 1957 | − reclaim_stat->recent_rotated[1] = stat.nr_activate[1]; | |
| 1956 | + reclaim_stat->recent_rotated[0] += stat.nr_activate[0]; | |
| 1957 | + reclaim_stat->recent_rotated[1] += stat.nr_activate[1]; | |
| 1958 | 1958 | |
| 1959 | 1959 | move_pages_to_lru(lruvec, &page_list); |
| 1960 | 1960 | |
| @@ -73,7 +73,7 @@ parse_symbol() { · 72 unmodified lines | ||
| 73 | 73 | if [[ "${cache[$module,$address]+isset}" == "isset" ]]; then |
| 74 | 74 | local code=${cache[$module,$address]} |
| 75 | 75 | else |
| 76 | − local code=$(addr2line -i -e "$objfile" "$address") | |
| 76 | + local code=$(${CROSS_COMPILE}addr2line -i -e "$objfile" "$address") | |
| 77 | 77 | cache[$module,$address]=$code |
| 78 | 78 | fi |
| 79 | 79 | |
| @@ -100,7 +100,9 @@ static void nfit_test_kill(void *_pgmap) · 99 unmodified lines | ||
| 100 | 100 | { |
| 101 | 101 | struct dev_pagemap *pgmap = _pgmap; |
| 102 | 102 | |
| 103 | + WARN_ON(!pgmap || !pgmap->ref || !pgmap->kill || !pgmap->cleanup); | |
| 103 | 104 | pgmap->kill(pgmap->ref); |
| 105 | + pgmap->cleanup(pgmap->ref); | |
| 104 | 106 | } |
| 105 | 107 | |
| 106 | 108 | void *__wrap_devm_memremap_pages(struct device *dev, struct dev_pagemap *pgmap) |