diff options
Diffstat (limited to 'fs/bio.c')
-rw-r--r-- | fs/bio.c | 71 |
1 files changed, 37 insertions, 34 deletions
@@ -301,48 +301,51 @@ void bio_init(struct bio *bio) | |||
301 | **/ | 301 | **/ |
302 | struct bio *bio_alloc_bioset(gfp_t gfp_mask, int nr_iovecs, struct bio_set *bs) | 302 | struct bio *bio_alloc_bioset(gfp_t gfp_mask, int nr_iovecs, struct bio_set *bs) |
303 | { | 303 | { |
304 | struct bio_vec *bvl = NULL; | ||
304 | struct bio *bio = NULL; | 305 | struct bio *bio = NULL; |
305 | void *uninitialized_var(p); | 306 | unsigned long idx = 0; |
307 | void *p = NULL; | ||
306 | 308 | ||
307 | if (bs) { | 309 | if (bs) { |
308 | p = mempool_alloc(bs->bio_pool, gfp_mask); | 310 | p = mempool_alloc(bs->bio_pool, gfp_mask); |
309 | 311 | if (!p) | |
310 | if (p) | 312 | goto err; |
311 | bio = p + bs->front_pad; | 313 | bio = p + bs->front_pad; |
312 | } else | 314 | } else { |
313 | bio = kmalloc(sizeof(*bio), gfp_mask); | 315 | bio = kmalloc(sizeof(*bio), gfp_mask); |
316 | if (!bio) | ||
317 | goto err; | ||
318 | } | ||
314 | 319 | ||
315 | if (likely(bio)) { | 320 | bio_init(bio); |
316 | struct bio_vec *bvl = NULL; | 321 | |
317 | 322 | if (unlikely(!nr_iovecs)) | |
318 | bio_init(bio); | 323 | goto out_set; |
319 | if (likely(nr_iovecs)) { | 324 | |
320 | unsigned long uninitialized_var(idx); | 325 | if (nr_iovecs <= BIO_INLINE_VECS) { |
321 | 326 | bvl = bio->bi_inline_vecs; | |
322 | if (nr_iovecs <= BIO_INLINE_VECS) { | 327 | nr_iovecs = BIO_INLINE_VECS; |
323 | idx = 0; | 328 | } else { |
324 | bvl = bio->bi_inline_vecs; | 329 | bvl = bvec_alloc_bs(gfp_mask, nr_iovecs, &idx, bs); |
325 | nr_iovecs = BIO_INLINE_VECS; | 330 | if (unlikely(!bvl)) |
326 | } else { | 331 | goto err_free; |
327 | bvl = bvec_alloc_bs(gfp_mask, nr_iovecs, &idx, | 332 | |
328 | bs); | 333 | nr_iovecs = bvec_nr_vecs(idx); |
329 | nr_iovecs = bvec_nr_vecs(idx); | ||
330 | } | ||
331 | if (unlikely(!bvl)) { | ||
332 | if (bs) | ||
333 | mempool_free(p, bs->bio_pool); | ||
334 | else | ||
335 | kfree(bio); | ||
336 | bio = NULL; | ||
337 | goto out; | ||
338 | } | ||
339 | bio->bi_flags |= idx << BIO_POOL_OFFSET; | ||
340 | bio->bi_max_vecs = nr_iovecs; | ||
341 | } | ||
342 | bio->bi_io_vec = bvl; | ||
343 | } | 334 | } |
344 | out: | 335 | bio->bi_flags |= idx << BIO_POOL_OFFSET; |
336 | bio->bi_max_vecs = nr_iovecs; | ||
337 | out_set: | ||
338 | bio->bi_io_vec = bvl; | ||
339 | |||
345 | return bio; | 340 | return bio; |
341 | |||
342 | err_free: | ||
343 | if (bs) | ||
344 | mempool_free(p, bs->bio_pool); | ||
345 | else | ||
346 | kfree(bio); | ||
347 | err: | ||
348 | return NULL; | ||
346 | } | 349 | } |
347 | 350 | ||
348 | struct bio *bio_alloc(gfp_t gfp_mask, int nr_iovecs) | 351 | struct bio *bio_alloc(gfp_t gfp_mask, int nr_iovecs) |