/** * bio_alloc_bioset - allocate a bio for I/O * @gfp_mask: the GFP_* mask given to the slab allocator * @nr_iovecs: number of iovecs to pre-allocate * @bs: the bio_set to allocate from. * * Description: * If @bs is NULL, uses kmalloc() to allocate the bio; else the allocation is * backed by the @bs's mempool. * * When @bs is not NULL, if %__GFP_DIRECT_RECLAIM is set then bio_alloc will * always be able to allocate a bio. This is due to the mempool guarantees. * To make this work, callers must never allocate more than 1 bio at a time * from this pool. Callers that need to allocate more than 1 bio must always * submit the previously allocated bio for IO before attempting to allocate * a new one. Failure to do so can cause deadlocks under memory pressure. * * Note that when running under generic_make_request() (i.e. any block * driver), bios are not submitted until after you return - see the code in * generic_make_request() that converts recursion into iteration, to prevent * stack overflows. * * This would normally mean allocating multiple bios under * generic_make_request() would be susceptible to deadlocks, but we have * deadlock avoidance code that resubmits any blocked bios from a rescuer * thread. * * However, we do not guarantee forward progress for allocations from other * mempools. Doing multiple allocations from the same mempool under * generic_make_request() should be avoided - instead, use bio_set's front_pad * for per bio allocations. * * RETURNS: * Pointer to new bio on success, NULL on failure. */ struct bio *bio_alloc_bioset(gfp_t gfp_mask, unsigned int nr_iovecs, struct bio_set *bs) { gfp_t saved_gfp = gfp_mask; unsigned front_pad; unsigned inline_vecs; struct bio_vec *bvl = NULL; struct bio *bio; void *p; if (!bs) { if (nr_iovecs > UIO_MAXIOV) return NULL; p = kmalloc(sizeof(struct bio) + nr_iovecs * sizeof(struct bio_vec), gfp_mask); front_pad = 0; inline_vecs = nr_iovecs; } else { /* should not use nobvec bioset for nr_iovecs > 0 */ if (WARN_ON_ONCE(!bs->bvec_pool && nr_iovecs > 0)) return NULL; /* * generic_make_request() converts recursion to iteration; this * means if we're running beneath it, any bios we allocate and * submit will not be submitted (and thus freed) until after we * return. * * This exposes us to a potential deadlock if we allocate * multiple bios from the same bio_set() while running * underneath generic_make_request(). If we were to allocate * multiple bios (say a stacking block driver that was splitting * bios), we would deadlock if we exhausted the mempool's * reserve. * * We solve this, and guarantee forward progress, with a rescuer * workqueue per bio_set. If we go to allocate and there are * bios on current->bio_list, we first try the allocation * without __GFP_DIRECT_RECLAIM; if that fails, we punt those * bios we would be blocking to the rescuer workqueue before * we retry with the original gfp_flags. */ if (current->bio_list && (!bio_list_empty(¤t->bio_list[0]) || !bio_list_empty(¤t->bio_list[1])) && bs->rescue_workqueue) gfp_mask &= ~__GFP_DIRECT_RECLAIM; p = mempool_alloc(bs->bio_pool, gfp_mask); if (!p && gfp_mask != saved_gfp) { punt_bios_to_rescuer(bs); gfp_mask = saved_gfp; p = mempool_alloc(bs->bio_pool, gfp_mask); } front_pad = bs->front_pad; inline_vecs = BIO_INLINE_VECS; } if (unlikely(!p)) return NULL; bio = p + front_pad; bio_init(bio, NULL, 0); if (nr_iovecs > inline_vecs) { unsigned long idx = 0; bvl = bvec_alloc(gfp_mask, nr_iovecs, &idx, bs->bvec_pool); if (!bvl && gfp_mask != saved_gfp) { punt_bios_to_rescuer(bs); gfp_mask = saved_gfp; bvl = bvec_alloc(gfp_mask, nr_iovecs, &idx, bs->bvec_pool); } if (unlikely(!bvl)) goto err_free; bio->bi_flags |= idx << BVEC_POOL_OFFSET; } else if (nr_iovecs) { bvl = bio->bi_inline_vecs; } bio->bi_pool = bs; bio->bi_max_vecs = nr_iovecs; bio->bi_io_vec = bvl; return bio; err_free: mempool_free(p, bs->bio_pool); return NULL; }
static inline void free_tio(struct mapped_device *md, struct target_io *tio) { mempool_free(tio, md->tio_pool); }
int main(void) { MemPool test; MemBucket *bucks[SIZE]; MemBucket *bucket = NULL; int i; //char *stuffs[4] = { "eenie", "meenie", "minie", "moe" }; char *stuffs2[36] = { "1eenie", "2meenie", "3minie", " 4moe", "1xxxxx", "2yyyyyy", "3zzzzz", " 4qqqq", "1eenie", "2meenie", "3minie", " 4moe", "1eenie", "2meenie", "3minie", " 4moe", "1eenie", "2meenie", "3minie", " 4moe", "1eenie", "2meenie", "3minie", " 4moe", "1eenie", "2meenie", "3minie", " 4moe", "1eenie", "2meenie", "3minie", " 4moe", "1eenie", "2meenie", "3minie", " 4moe" }; if(mempool_init(&test, 36, 256)) { printf("error in mempool initialization\n"); } for(i = 0; i < 36; i++) { if((bucks[i] = mempool_alloc(&test)) == NULL) { printf("error in mempool_alloc: i=%d\n", i); continue; } bucket = bucks[i]; bucket->data = strncpy(bucket->data, stuffs2[i], 256); printf("bucket->key: %p\n", bucket->key); printf("bucket->data: %s\n", (char *) bucket->data); } for(i = 0; i < 2; i++) { mempool_free(&test, bucks[i]); bucks[i] = NULL; } for(i = 0; i < 14; i++) { if((bucks[i] = mempool_alloc(&test)) == NULL) { printf("error in mempool_alloc: i=%d\n", i); continue; } bucket = bucks[i]; bucket->data = strncpy(bucket->data, stuffs2[i], 256); printf("bucket->key: %p\n", bucket->key); printf("bucket->data: %s\n", (char *) bucket->data); } printf("free: %u, used: %u\n", test.free_list.size, test.used_list.size); return 0; }
static inline void free_io(struct mapped_device *md, struct dm_io *io) { mempool_free(io, md->io_pool); }
void flashcache_free_pending_job(struct pending_job *job) { mempool_free(job, _pending_job_pool); atomic_dec(&nr_pending_jobs); }
void flashcache_free_cache_job(struct kcached_job *job) { mempool_free(job, _job_pool); atomic_dec(&nr_cache_jobs); }
static int aoeblk_make_request(struct request_queue *q, struct bio *bio) { struct sk_buff_head queue; struct aoedev *d; struct buf *buf; ulong flags; blk_queue_bounce(q, &bio); if (bio == NULL) { ; BUG(); return 0; } d = bio->bi_bdev->bd_disk->private_data; if (d == NULL) { ; BUG(); bio_endio(bio, -ENXIO); return 0; } else if (bio->bi_io_vec == NULL) { ; BUG(); bio_endio(bio, -ENXIO); return 0; } buf = mempool_alloc(d->bufpool, GFP_NOIO); if (buf == NULL) { ; bio_endio(bio, -ENOMEM); return 0; } memset(buf, 0, sizeof(*buf)); INIT_LIST_HEAD(&buf->bufs); buf->stime = jiffies; buf->bio = bio; buf->resid = bio->bi_size; buf->sector = bio->bi_sector; buf->bv = &bio->bi_io_vec[bio->bi_idx]; buf->bv_resid = buf->bv->bv_len; WARN_ON(buf->bv_resid == 0); buf->bv_off = buf->bv->bv_offset; spin_lock_irqsave(&d->lock, flags); if ((d->flags & DEVFL_UP) == 0) { pr_info_ratelimited("aoe: device %ld.%d is not up\n", d->aoemajor, d->aoeminor); spin_unlock_irqrestore(&d->lock, flags); mempool_free(buf, d->bufpool); bio_endio(bio, -ENXIO); return 0; } list_add_tail(&buf->bufs, &d->bufq); aoecmd_work(d); __skb_queue_head_init(&queue); skb_queue_splice_init(&d->sendq, &queue); spin_unlock_irqrestore(&d->lock, flags); aoenet_xmit(&queue); return 0; }
struct nearest_map *nearest_init(const colormap *map) { mempool m = NULL; struct nearest_map *centroids = mempool_new(&m, sizeof(*centroids)); centroids->mempool = m; unsigned int skipped=0; unsigned int skip_index[map->colors]; for(unsigned int j=0; j < map->colors; j++) skip_index[j]=0; colormap *subset_palette = get_subset_palette(map); const int selected_heads = subset_palette->colors; centroids->heads = mempool_new(¢roids->mempool, sizeof(centroids->heads[0])*(selected_heads+1)); // +1 is fallback head unsigned int h=0; for(; h < selected_heads; h++) { unsigned int num_candiadtes = 1+(map->colors - skipped)/((1+selected_heads-h)/2); centroids->heads[h] = build_head(subset_palette->palette[h].acolor, map, num_candiadtes, ¢roids->mempool, skip_index, &skipped); if (centroids->heads[h].num_candidates == 0) { break; } } centroids->heads[h].radius = MAX_DIFF; centroids->heads[h].center = (f_pixel){0,0,0,0}; centroids->heads[h].num_candidates = 0; centroids->heads[h].candidates = mempool_new(¢roids->mempool, (map->colors - skipped) * sizeof(centroids->heads[h].candidates[0])); for(unsigned int i=0; i < map->colors; i++) { if (skip_index[i]) continue; centroids->heads[h].candidates[centroids->heads[h].num_candidates++] = (struct color_entry) { .color = map->palette[i].acolor, .index = i, .radius = 999, }; } centroids->num_heads = ++h; // get_subset_palette could have created a copy if (subset_palette != map->subset_palette) { pam_freecolormap(subset_palette); } return centroids; } unsigned int nearest_search(const struct nearest_map *centroids, const f_pixel px, const float min_opaque_val, float *diff) { const int iebug = px.a > min_opaque_val; const struct head *const heads = centroids->heads; for(unsigned int i=0; i < centroids->num_heads; i++) { float headdist = colordifference(px, heads[i].center); if (headdist <= heads[i].radius) { assert(heads[i].num_candidates); unsigned int ind=heads[i].candidates[0].index; float dist = colordifference(px, heads[i].candidates[0].color); /* penalty for making holes in IE */ if (iebug && heads[i].candidates[0].color.a < 1) { dist += 1.f/1024.f; } for(unsigned int j=1; j < heads[i].num_candidates; j++) { float newdist = colordifference(px, heads[i].candidates[j].color); /* penalty for making holes in IE */ if (iebug && heads[i].candidates[j].color.a < 1) { newdist += 1.f/1024.f; } if (newdist < dist) { dist = newdist; ind = heads[i].candidates[j].index; } } if (diff) *diff = dist; return ind; } } assert(0); return 0; } void nearest_free(struct nearest_map *centroids) { mempool_free(centroids->mempool); }