block: Add bio_alloc_pages()
More utility code to replace stuff that's getting open coded. Signed-off-by: Kent Overstreet <koverstreet@google.com> CC: Jens Axboe <axboe@kernel.dk> CC: NeilBrown <neilb@suse.de>
This commit is contained in:
		
					parent
					
						
							
								cb34e057ad
							
						
					
				
			
			
				commit
				
					
						a07876064a
					
				
			
		
					 3 changed files with 32 additions and 13 deletions
				
			
		|  | @ -92,7 +92,6 @@ static void r1bio_pool_free(void *r1_bio, void *data) | |||
| static void * r1buf_pool_alloc(gfp_t gfp_flags, void *data) | ||||
| { | ||||
| 	struct pool_info *pi = data; | ||||
| 	struct page *page; | ||||
| 	struct r1bio *r1_bio; | ||||
| 	struct bio *bio; | ||||
| 	int i, j; | ||||
|  | @ -122,14 +121,10 @@ static void * r1buf_pool_alloc(gfp_t gfp_flags, void *data) | |||
| 		j = 1; | ||||
| 	while(j--) { | ||||
| 		bio = r1_bio->bios[j]; | ||||
| 		for (i = 0; i < RESYNC_PAGES; i++) { | ||||
| 			page = alloc_page(gfp_flags); | ||||
| 			if (unlikely(!page)) | ||||
| 				goto out_free_pages; | ||||
| 		bio->bi_vcnt = RESYNC_PAGES; | ||||
| 
 | ||||
| 			bio->bi_io_vec[i].bv_page = page; | ||||
| 			bio->bi_vcnt = i+1; | ||||
| 		} | ||||
| 		if (bio_alloc_pages(bio, gfp_flags)) | ||||
| 			goto out_free_bio; | ||||
| 	} | ||||
| 	/* If not user-requests, copy the page pointers to all bios */ | ||||
| 	if (!test_bit(MD_RECOVERY_REQUESTED, &pi->mddev->recovery)) { | ||||
|  | @ -143,11 +138,6 @@ static void * r1buf_pool_alloc(gfp_t gfp_flags, void *data) | |||
| 
 | ||||
| 	return r1_bio; | ||||
| 
 | ||||
| out_free_pages: | ||||
| 	for (j=0 ; j < pi->raid_disks; j++) | ||||
| 		for (i=0; i < r1_bio->bios[j]->bi_vcnt ; i++) | ||||
| 			put_page(r1_bio->bios[j]->bi_io_vec[i].bv_page); | ||||
| 	j = -1; | ||||
| out_free_bio: | ||||
| 	while (++j < pi->raid_disks) | ||||
| 		bio_put(r1_bio->bios[j]); | ||||
|  |  | |||
							
								
								
									
										28
									
								
								fs/bio.c
									
										
									
									
									
								
							
							
						
						
									
										28
									
								
								fs/bio.c
									
										
									
									
									
								
							|  | @ -829,6 +829,34 @@ void bio_advance(struct bio *bio, unsigned bytes) | |||
| } | ||||
| EXPORT_SYMBOL(bio_advance); | ||||
| 
 | ||||
| /**
 | ||||
|  * bio_alloc_pages - allocates a single page for each bvec in a bio | ||||
|  * @bio: bio to allocate pages for | ||||
|  * @gfp_mask: flags for allocation | ||||
|  * | ||||
|  * Allocates pages up to @bio->bi_vcnt. | ||||
|  * | ||||
|  * Returns 0 on success, -ENOMEM on failure. On failure, any allocated pages are | ||||
|  * freed. | ||||
|  */ | ||||
| int bio_alloc_pages(struct bio *bio, gfp_t gfp_mask) | ||||
| { | ||||
| 	int i; | ||||
| 	struct bio_vec *bv; | ||||
| 
 | ||||
| 	bio_for_each_segment_all(bv, bio, i) { | ||||
| 		bv->bv_page = alloc_page(gfp_mask); | ||||
| 		if (!bv->bv_page) { | ||||
| 			while (--bv >= bio->bi_io_vec) | ||||
| 				__free_page(bv->bv_page); | ||||
| 			return -ENOMEM; | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| EXPORT_SYMBOL(bio_alloc_pages); | ||||
| 
 | ||||
| /**
 | ||||
|  * bio_copy_data - copy contents of data buffers from one chain of bios to | ||||
|  * another | ||||
|  |  | |||
|  | @ -298,6 +298,7 @@ static inline void bio_flush_dcache_pages(struct bio *bi) | |||
| #endif | ||||
| 
 | ||||
| extern void bio_copy_data(struct bio *dst, struct bio *src); | ||||
| extern int bio_alloc_pages(struct bio *bio, gfp_t gfp); | ||||
| 
 | ||||
| extern struct bio *bio_copy_user(struct request_queue *, struct rq_map_data *, | ||||
| 				 unsigned long, unsigned int, int, gfp_t); | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Kent Overstreet
				Kent Overstreet