diff options
Diffstat (limited to 'fs/bio.c')
-rw-r--r-- | fs/bio.c | 191 |
1 files changed, 161 insertions, 30 deletions
@@ -31,8 +31,6 @@ | |||
31 | 31 | ||
32 | DEFINE_TRACE(block_split); | 32 | DEFINE_TRACE(block_split); |
33 | 33 | ||
34 | static struct kmem_cache *bio_slab __read_mostly; | ||
35 | |||
36 | static mempool_t *bio_split_pool __read_mostly; | 34 | static mempool_t *bio_split_pool __read_mostly; |
37 | 35 | ||
38 | /* | 36 | /* |
@@ -40,9 +38,8 @@ static mempool_t *bio_split_pool __read_mostly; | |||
40 | * break badly! cannot be bigger than what you can fit into an | 38 | * break badly! cannot be bigger than what you can fit into an |
41 | * unsigned short | 39 | * unsigned short |
42 | */ | 40 | */ |
43 | |||
44 | #define BV(x) { .nr_vecs = x, .name = "biovec-"__stringify(x) } | 41 | #define BV(x) { .nr_vecs = x, .name = "biovec-"__stringify(x) } |
45 | static struct biovec_slab bvec_slabs[BIOVEC_NR_POOLS] __read_mostly = { | 42 | struct biovec_slab bvec_slabs[BIOVEC_NR_POOLS] __read_mostly = { |
46 | BV(1), BV(4), BV(16), BV(64), BV(128), BV(BIO_MAX_PAGES), | 43 | BV(1), BV(4), BV(16), BV(64), BV(128), BV(BIO_MAX_PAGES), |
47 | }; | 44 | }; |
48 | #undef BV | 45 | #undef BV |
@@ -53,11 +50,119 @@ static struct biovec_slab bvec_slabs[BIOVEC_NR_POOLS] __read_mostly = { | |||
53 | */ | 50 | */ |
54 | struct bio_set *fs_bio_set; | 51 | struct bio_set *fs_bio_set; |
55 | 52 | ||
53 | /* | ||
54 | * Our slab pool management | ||
55 | */ | ||
56 | struct bio_slab { | ||
57 | struct kmem_cache *slab; | ||
58 | unsigned int slab_ref; | ||
59 | unsigned int slab_size; | ||
60 | char name[8]; | ||
61 | }; | ||
62 | static DEFINE_MUTEX(bio_slab_lock); | ||
63 | static struct bio_slab *bio_slabs; | ||
64 | static unsigned int bio_slab_nr, bio_slab_max; | ||
65 | |||
66 | static struct kmem_cache *bio_find_or_create_slab(unsigned int extra_size) | ||
67 | { | ||
68 | unsigned int sz = sizeof(struct bio) + extra_size; | ||
69 | struct kmem_cache *slab = NULL; | ||
70 | struct bio_slab *bslab; | ||
71 | unsigned int i, entry = -1; | ||
72 | |||
73 | mutex_lock(&bio_slab_lock); | ||
74 | |||
75 | i = 0; | ||
76 | while (i < bio_slab_nr) { | ||
77 | struct bio_slab *bslab = &bio_slabs[i]; | ||
78 | |||
79 | if (!bslab->slab && entry == -1) | ||
80 | entry = i; | ||
81 | else if (bslab->slab_size == sz) { | ||
82 | slab = bslab->slab; | ||
83 | bslab->slab_ref++; | ||
84 | break; | ||
85 | } | ||
86 | i++; | ||
87 | } | ||
88 | |||
89 | if (slab) | ||
90 | goto out_unlock; | ||
91 | |||
92 | if (bio_slab_nr == bio_slab_max && entry == -1) { | ||
93 | bio_slab_max <<= 1; | ||
94 | bio_slabs = krealloc(bio_slabs, | ||
95 | bio_slab_max * sizeof(struct bio_slab), | ||
96 | GFP_KERNEL); | ||
97 | if (!bio_slabs) | ||
98 | goto out_unlock; | ||
99 | } | ||
100 | if (entry == -1) | ||
101 | entry = bio_slab_nr++; | ||
102 | |||
103 | bslab = &bio_slabs[entry]; | ||
104 | |||
105 | snprintf(bslab->name, sizeof(bslab->name), "bio-%d", entry); | ||
106 | slab = kmem_cache_create(bslab->name, sz, 0, SLAB_HWCACHE_ALIGN, NULL); | ||
107 | if (!slab) | ||
108 | goto out_unlock; | ||
109 | |||
110 | printk("bio: create slab <%s> at %d\n", bslab->name, entry); | ||
111 | bslab->slab = slab; | ||
112 | bslab->slab_ref = 1; | ||
113 | bslab->slab_size = sz; | ||
114 | out_unlock: | ||
115 | mutex_unlock(&bio_slab_lock); | ||
116 | return slab; | ||
117 | } | ||
118 | |||
119 | static void bio_put_slab(struct bio_set *bs) | ||
120 | { | ||
121 | struct bio_slab *bslab = NULL; | ||
122 | unsigned int i; | ||
123 | |||
124 | mutex_lock(&bio_slab_lock); | ||
125 | |||
126 | for (i = 0; i < bio_slab_nr; i++) { | ||
127 | if (bs->bio_slab == bio_slabs[i].slab) { | ||
128 | bslab = &bio_slabs[i]; | ||
129 | break; | ||
130 | } | ||
131 | } | ||
132 | |||
133 | if (WARN(!bslab, KERN_ERR "bio: unable to find slab!\n")) | ||
134 | goto out; | ||
135 | |||
136 | WARN_ON(!bslab->slab_ref); | ||
137 | |||
138 | if (--bslab->slab_ref) | ||
139 | goto out; | ||
140 | |||
141 | kmem_cache_destroy(bslab->slab); | ||
142 | bslab->slab = NULL; | ||
143 | |||
144 | out: | ||
145 | mutex_unlock(&bio_slab_lock); | ||
146 | } | ||
147 | |||
56 | unsigned int bvec_nr_vecs(unsigned short idx) | 148 | unsigned int bvec_nr_vecs(unsigned short idx) |
57 | { | 149 | { |
58 | return bvec_slabs[idx].nr_vecs; | 150 | return bvec_slabs[idx].nr_vecs; |
59 | } | 151 | } |
60 | 152 | ||
153 | void bvec_free_bs(struct bio_set *bs, struct bio_vec *bv, unsigned int idx) | ||
154 | { | ||
155 | BIO_BUG_ON(idx >= BIOVEC_NR_POOLS); | ||
156 | |||
157 | if (idx == BIOVEC_MAX_IDX) | ||
158 | mempool_free(bv, bs->bvec_pool); | ||
159 | else { | ||
160 | struct biovec_slab *bvs = bvec_slabs + idx; | ||
161 | |||
162 | kmem_cache_free(bvs->slab, bv); | ||
163 | } | ||
164 | } | ||
165 | |||
61 | struct bio_vec *bvec_alloc_bs(gfp_t gfp_mask, int nr, unsigned long *idx, | 166 | struct bio_vec *bvec_alloc_bs(gfp_t gfp_mask, int nr, unsigned long *idx, |
62 | struct bio_set *bs) | 167 | struct bio_set *bs) |
63 | { | 168 | { |
@@ -134,24 +239,22 @@ fallback: | |||
134 | 239 | ||
135 | void bio_free(struct bio *bio, struct bio_set *bs) | 240 | void bio_free(struct bio *bio, struct bio_set *bs) |
136 | { | 241 | { |
137 | if (bio->bi_io_vec) { | 242 | void *p; |
138 | const int pool_idx = BIO_POOL_IDX(bio); | ||
139 | 243 | ||
140 | BIO_BUG_ON(pool_idx >= BIOVEC_NR_POOLS); | 244 | if (bio->bi_io_vec) |
141 | 245 | bvec_free_bs(bs, bio->bi_io_vec, BIO_POOL_IDX(bio)); | |
142 | if (pool_idx == BIOVEC_MAX_IDX) | ||
143 | mempool_free(bio->bi_io_vec, bs->bvec_pool); | ||
144 | else { | ||
145 | struct biovec_slab *bvs = bvec_slabs + pool_idx; | ||
146 | |||
147 | kmem_cache_free(bvs->slab, bio->bi_io_vec); | ||
148 | } | ||
149 | } | ||
150 | 246 | ||
151 | if (bio_integrity(bio)) | 247 | if (bio_integrity(bio)) |
152 | bio_integrity_free(bio, bs); | 248 | bio_integrity_free(bio, bs); |
153 | 249 | ||
154 | mempool_free(bio, bs->bio_pool); | 250 | /* |
251 | * If we have front padding, adjust the bio pointer before freeing | ||
252 | */ | ||
253 | p = bio; | ||
254 | if (bs->front_pad) | ||
255 | p -= bs->front_pad; | ||
256 | |||
257 | mempool_free(p, bs->bio_pool); | ||
155 | } | 258 | } |
156 | 259 | ||
157 | /* | 260 | /* |
@@ -188,16 +291,20 @@ void bio_init(struct bio *bio) | |||
188 | * for a &struct bio to become free. If a %NULL @bs is passed in, we will | 291 | * for a &struct bio to become free. If a %NULL @bs is passed in, we will |
189 | * fall back to just using @kmalloc to allocate the required memory. | 292 | * fall back to just using @kmalloc to allocate the required memory. |
190 | * | 293 | * |
191 | * allocate bio and iovecs from the memory pools specified by the | 294 | * Note that the caller must set ->bi_destructor on succesful return |
192 | * bio_set structure, or @kmalloc if none given. | 295 | * of a bio, to do the appropriate freeing of the bio once the reference |
296 | * count drops to zero. | ||
193 | **/ | 297 | **/ |
194 | struct bio *bio_alloc_bioset(gfp_t gfp_mask, int nr_iovecs, struct bio_set *bs) | 298 | struct bio *bio_alloc_bioset(gfp_t gfp_mask, int nr_iovecs, struct bio_set *bs) |
195 | { | 299 | { |
196 | struct bio *bio; | 300 | struct bio *bio = NULL; |
301 | |||
302 | if (bs) { | ||
303 | void *p = mempool_alloc(bs->bio_pool, gfp_mask); | ||
197 | 304 | ||
198 | if (bs) | 305 | if (p) |
199 | bio = mempool_alloc(bs->bio_pool, gfp_mask); | 306 | bio = p + bs->front_pad; |
200 | else | 307 | } else |
201 | bio = kmalloc(sizeof(*bio), gfp_mask); | 308 | bio = kmalloc(sizeof(*bio), gfp_mask); |
202 | 309 | ||
203 | if (likely(bio)) { | 310 | if (likely(bio)) { |
@@ -1398,11 +1505,25 @@ void bioset_free(struct bio_set *bs) | |||
1398 | 1505 | ||
1399 | bioset_integrity_free(bs); | 1506 | bioset_integrity_free(bs); |
1400 | biovec_free_pools(bs); | 1507 | biovec_free_pools(bs); |
1508 | bio_put_slab(bs); | ||
1401 | 1509 | ||
1402 | kfree(bs); | 1510 | kfree(bs); |
1403 | } | 1511 | } |
1404 | 1512 | ||
1405 | struct bio_set *bioset_create(int bio_pool_size, int bvec_pool_size) | 1513 | /** |
1514 | * bioset_create - Create a bio_set | ||
1515 | * @pool_size: Number of bio and bio_vecs to cache in the mempool | ||
1516 | * @front_pad: Number of bytes to allocate in front of the returned bio | ||
1517 | * | ||
1518 | * Description: | ||
1519 | * Set up a bio_set to be used with @bio_alloc_bioset. Allows the caller | ||
1520 | * to ask for a number of bytes to be allocated in front of the bio. | ||
1521 | * Front pad allocation is useful for embedding the bio inside | ||
1522 | * another structure, to avoid allocating extra data to go with the bio. | ||
1523 | * Note that the bio must be embedded at the END of that structure always, | ||
1524 | * or things will break badly. | ||
1525 | */ | ||
1526 | struct bio_set *bioset_create(unsigned int pool_size, unsigned int front_pad) | ||
1406 | { | 1527 | { |
1407 | struct bio_set *bs; | 1528 | struct bio_set *bs; |
1408 | 1529 | ||
@@ -1410,16 +1531,22 @@ struct bio_set *bioset_create(int bio_pool_size, int bvec_pool_size) | |||
1410 | if (!bs) | 1531 | if (!bs) |
1411 | return NULL; | 1532 | return NULL; |
1412 | 1533 | ||
1413 | bs->bio_slab = bio_slab; | 1534 | bs->front_pad = front_pad; |
1414 | 1535 | ||
1415 | bs->bio_pool = mempool_create_slab_pool(bio_pool_size, bs->bio_slab); | 1536 | bs->bio_slab = bio_find_or_create_slab(front_pad); |
1537 | if (!bs->bio_slab) { | ||
1538 | kfree(bs); | ||
1539 | return NULL; | ||
1540 | } | ||
1541 | |||
1542 | bs->bio_pool = mempool_create_slab_pool(pool_size, bs->bio_slab); | ||
1416 | if (!bs->bio_pool) | 1543 | if (!bs->bio_pool) |
1417 | goto bad; | 1544 | goto bad; |
1418 | 1545 | ||
1419 | if (bioset_integrity_create(bs, bio_pool_size)) | 1546 | if (bioset_integrity_create(bs, pool_size)) |
1420 | goto bad; | 1547 | goto bad; |
1421 | 1548 | ||
1422 | if (!biovec_create_pools(bs, bvec_pool_size)) | 1549 | if (!biovec_create_pools(bs, pool_size)) |
1423 | return bs; | 1550 | return bs; |
1424 | 1551 | ||
1425 | bad: | 1552 | bad: |
@@ -1443,12 +1570,16 @@ static void __init biovec_init_slabs(void) | |||
1443 | 1570 | ||
1444 | static int __init init_bio(void) | 1571 | static int __init init_bio(void) |
1445 | { | 1572 | { |
1446 | bio_slab = KMEM_CACHE(bio, SLAB_HWCACHE_ALIGN|SLAB_PANIC); | 1573 | bio_slab_max = 2; |
1574 | bio_slab_nr = 0; | ||
1575 | bio_slabs = kzalloc(bio_slab_max * sizeof(struct bio_slab), GFP_KERNEL); | ||
1576 | if (!bio_slabs) | ||
1577 | panic("bio: can't allocate bios\n"); | ||
1447 | 1578 | ||
1448 | bio_integrity_init_slab(); | 1579 | bio_integrity_init_slab(); |
1449 | biovec_init_slabs(); | 1580 | biovec_init_slabs(); |
1450 | 1581 | ||
1451 | fs_bio_set = bioset_create(BIO_POOL_SIZE, 2); | 1582 | fs_bio_set = bioset_create(BIO_POOL_SIZE, 0); |
1452 | if (!fs_bio_set) | 1583 | if (!fs_bio_set) |
1453 | panic("bio: can't allocate bios\n"); | 1584 | panic("bio: can't allocate bios\n"); |
1454 | 1585 | ||