Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

lib/genalloc: introduce chunk owners

The p2pdma facility enables a provider to publish a pool of dma
addresses for a consumer to allocate. A genpool is used internally by
p2pdma to collect dma resources, 'chunks', to be handed out to
consumers. Whenever a consumer allocates a resource it needs to pin the
'struct dev_pagemap' instance that backs the chunk selected by
pci_alloc_p2pmem().

Currently that reference is taken globally on the entire provider
device. That sets up a lifetime mismatch whereby the p2pdma core needs
to maintain hacks to make sure the percpu_ref is not released twice.

This lifetime mismatch also stands in the way of a fix to
devm_memremap_pages() whereby devm_memremap_pages_release() must wait for
the percpu_ref ->release() callback to complete before it can proceed to
teardown pages.

So, towards fixing this situation, introduce the ability to store a 'chunk
owner' at gen_pool_add() time, and a facility to retrieve the owner at
gen_pool_{alloc,free}() time. For p2pdma this will be used to store and
recall individual dev_pagemap reference counter instances per-chunk.

Link: http://lkml.kernel.org/r/155727338118.292046.13407378933221579644.stgit@dwillia2-desk3.amr.corp.intel.com
Signed-off-by: Dan Williams <dan.j.williams@intel.com>
Reviewed-by: Ira Weiny <ira.weiny@intel.com>
Reviewed-by: Logan Gunthorpe <logang@deltatee.com>
Cc: Bjorn Helgaas <bhelgaas@google.com>
Cc: "Jérôme Glisse" <jglisse@redhat.com>
Cc: Christoph Hellwig <hch@lst.de>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: "Rafael J. Wysocki" <rafael@kernel.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

authored by

Dan Williams and committed by
Linus Torvalds
795ee306 e615a191

+74 -32
+49 -6
include/linux/genalloc.h
··· 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 */ ··· 97 96 98 97 extern struct gen_pool *gen_pool_create(int, int); 99 98 extern phys_addr_t gen_pool_virt_to_phys(struct gen_pool *pool, unsigned long); 100 - extern int gen_pool_add_virt(struct gen_pool *, unsigned long, phys_addr_t, 101 - size_t, int); 99 + extern int gen_pool_add_owner(struct gen_pool *, unsigned long, phys_addr_t, 100 + size_t, int, void *); 101 + 102 + static inline int gen_pool_add_virt(struct gen_pool *pool, unsigned long addr, 103 + phys_addr_t phys, size_t size, int nid) 104 + { 105 + return gen_pool_add_owner(pool, addr, phys, size, nid, NULL); 106 + } 107 + 102 108 /** 103 109 * gen_pool_add - add a new chunk of special memory to the pool 104 110 * @pool: pool to add new memory chunk to ··· 124 116 return gen_pool_add_virt(pool, addr, -1, size, nid); 125 117 } 126 118 extern void gen_pool_destroy(struct gen_pool *); 127 - extern unsigned long gen_pool_alloc(struct gen_pool *, size_t); 128 - extern unsigned long gen_pool_alloc_algo(struct gen_pool *, size_t, 129 - genpool_algo_t algo, void *data); 119 + unsigned long gen_pool_alloc_algo_owner(struct gen_pool *pool, size_t size, 120 + genpool_algo_t algo, void *data, void **owner); 121 + 122 + static inline unsigned long gen_pool_alloc_owner(struct gen_pool *pool, 123 + size_t size, void **owner) 124 + { 125 + return gen_pool_alloc_algo_owner(pool, size, pool->algo, pool->data, 126 + owner); 127 + } 128 + 129 + static inline unsigned long gen_pool_alloc_algo(struct gen_pool *pool, 130 + size_t size, genpool_algo_t algo, void *data) 131 + { 132 + return gen_pool_alloc_algo_owner(pool, size, algo, data, NULL); 133 + } 134 + 135 + /** 136 + * gen_pool_alloc - allocate special memory from the pool 137 + * @pool: pool to allocate from 138 + * @size: number of bytes to allocate from the pool 139 + * 140 + * Allocate the requested number of bytes from the specified pool. 141 + * Uses the pool allocation function (with first-fit algorithm by default). 142 + * Can not be used in NMI handler on architectures without 143 + * NMI-safe cmpxchg implementation. 144 + */ 145 + static inline unsigned long gen_pool_alloc(struct gen_pool *pool, size_t size) 146 + { 147 + return gen_pool_alloc_algo(pool, size, pool->algo, pool->data); 148 + } 149 + 130 150 extern void *gen_pool_dma_alloc(struct gen_pool *pool, size_t size, 131 151 dma_addr_t *dma); 132 - extern void gen_pool_free(struct gen_pool *, unsigned long, size_t); 152 + extern void gen_pool_free_owner(struct gen_pool *pool, unsigned long addr, 153 + size_t size, void **owner); 154 + static inline void gen_pool_free(struct gen_pool *pool, unsigned long addr, 155 + size_t size) 156 + { 157 + gen_pool_free_owner(pool, addr, size, NULL); 158 + } 159 + 133 160 extern void gen_pool_for_each_chunk(struct gen_pool *, 134 161 void (*)(struct gen_pool *, struct gen_pool_chunk *, void *), void *); 135 162 extern size_t gen_pool_avail(struct gen_pool *);
+25 -26
lib/genalloc.c
··· 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; ··· 196 195 chunk->phys_addr = phys; 197 196 chunk->start_addr = virt; 198 197 chunk->end_addr = virt + size - 1; 198 + chunk->owner = owner; 199 199 atomic_long_set(&chunk->avail, size); 200 200 201 201 spin_lock(&pool->lock); ··· 205 203 206 204 return 0; 207 205 } 208 - EXPORT_SYMBOL(gen_pool_add_virt); 206 + EXPORT_SYMBOL(gen_pool_add_owner); 209 207 210 208 /** 211 209 * gen_pool_virt_to_phys - return the physical address of memory ··· 262 260 EXPORT_SYMBOL(gen_pool_destroy); 263 261 264 262 /** 265 - * gen_pool_alloc - allocate special memory from the pool 266 - * @pool: pool to allocate from 267 - * @size: number of bytes to allocate from the pool 268 - * 269 - * Allocate the requested number of bytes from the specified pool. 270 - * Uses the pool allocation function (with first-fit algorithm by default). 271 - * Can not be used in NMI handler on architectures without 272 - * NMI-safe cmpxchg implementation. 273 - */ 274 - unsigned long gen_pool_alloc(struct gen_pool *pool, size_t size) 275 - { 276 - return gen_pool_alloc_algo(pool, size, pool->algo, pool->data); 277 - } 278 - EXPORT_SYMBOL(gen_pool_alloc); 279 - 280 - /** 281 - * gen_pool_alloc_algo - allocate special memory from the pool 263 + * gen_pool_alloc_algo_owner - allocate special memory from the pool 282 264 * @pool: pool to allocate from 283 265 * @size: number of bytes to allocate from the pool 284 266 * @algo: algorithm passed from caller 285 267 * @data: data passed to algorithm 268 + * @owner: optionally retrieve the chunk owner 286 269 * 287 270 * Allocate the requested number of bytes from the specified pool. 288 271 * Uses the pool allocation function (with first-fit algorithm by default). 289 272 * Can not be used in NMI handler on architectures without 290 273 * NMI-safe cmpxchg implementation. 291 274 */ 292 - unsigned long gen_pool_alloc_algo(struct gen_pool *pool, size_t size, 293 - genpool_algo_t algo, void *data) 275 + unsigned long gen_pool_alloc_algo_owner(struct gen_pool *pool, size_t size, 276 + genpool_algo_t algo, void *data, void **owner) 294 277 { 295 278 struct gen_pool_chunk *chunk; 296 279 unsigned long addr = 0; ··· 285 298 #ifndef CONFIG_ARCH_HAVE_NMI_SAFE_CMPXCHG 286 299 BUG_ON(in_nmi()); 287 300 #endif 301 + 302 + if (owner) 303 + *owner = NULL; 288 304 289 305 if (size == 0) 290 306 return 0; ··· 316 326 addr = chunk->start_addr + ((unsigned long)start_bit << order); 317 327 size = nbits << order; 318 328 atomic_long_sub(size, &chunk->avail); 329 + if (owner) 330 + *owner = chunk->owner; 319 331 break; 320 332 } 321 333 rcu_read_unlock(); 322 334 return addr; 323 335 } 324 - EXPORT_SYMBOL(gen_pool_alloc_algo); 336 + EXPORT_SYMBOL(gen_pool_alloc_algo_owner); 325 337 326 338 /** 327 339 * gen_pool_dma_alloc - allocate special memory from the pool for DMA usage ··· 359 367 * @pool: pool to free to 360 368 * @addr: starting address of memory to free back to pool 361 369 * @size: size in bytes of memory to free 370 + * @owner: private data stashed at gen_pool_add() time 362 371 * 363 372 * Free previously allocated special memory back to the specified 364 373 * pool. Can not be used in NMI handler on architectures without 365 374 * NMI-safe cmpxchg implementation. 366 375 */ 367 - void gen_pool_free(struct gen_pool *pool, unsigned long addr, size_t size) 376 + void gen_pool_free_owner(struct gen_pool *pool, unsigned long addr, size_t size, 377 + void **owner) 368 378 { 369 379 struct gen_pool_chunk *chunk; 370 380 int order = pool->min_alloc_order; ··· 375 381 #ifndef CONFIG_ARCH_HAVE_NMI_SAFE_CMPXCHG 376 382 BUG_ON(in_nmi()); 377 383 #endif 384 + 385 + if (owner) 386 + *owner = NULL; 378 387 379 388 nbits = (size + (1UL << order) - 1) >> order; 380 389 rcu_read_lock(); ··· 389 392 BUG_ON(remain); 390 393 size = nbits << order; 391 394 atomic_long_add(size, &chunk->avail); 395 + if (owner) 396 + *owner = chunk->owner; 392 397 rcu_read_unlock(); 393 398 return; 394 399 } ··· 398 399 rcu_read_unlock(); 399 400 BUG(); 400 401 } 401 - EXPORT_SYMBOL(gen_pool_free); 402 + EXPORT_SYMBOL(gen_pool_free_owner); 402 403 403 404 /** 404 405 * gen_pool_for_each_chunk - call func for every chunk of generic memory pool