| xj | b04a402 | 2021-11-25 15:01:52 +0800 | [diff] [blame] | 1 | // SPDX-License-Identifier: GPL-2.0 | 
|  | 2 | /* Maximum size of each resync request */ | 
|  | 3 | #define RESYNC_BLOCK_SIZE (64*1024) | 
|  | 4 | #define RESYNC_PAGES ((RESYNC_BLOCK_SIZE + PAGE_SIZE-1) / PAGE_SIZE) | 
|  | 5 |  | 
|  | 6 | /* for managing resync I/O pages */ | 
|  | 7 | struct resync_pages { | 
|  | 8 | void		*raid_bio; | 
|  | 9 | struct page	*pages[RESYNC_PAGES]; | 
|  | 10 | }; | 
|  | 11 |  | 
|  | 12 | static inline int resync_alloc_pages(struct resync_pages *rp, | 
|  | 13 | gfp_t gfp_flags) | 
|  | 14 | { | 
|  | 15 | int i; | 
|  | 16 |  | 
|  | 17 | for (i = 0; i < RESYNC_PAGES; i++) { | 
|  | 18 | rp->pages[i] = alloc_page(gfp_flags); | 
|  | 19 | if (!rp->pages[i]) | 
|  | 20 | goto out_free; | 
|  | 21 | } | 
|  | 22 |  | 
|  | 23 | return 0; | 
|  | 24 |  | 
|  | 25 | out_free: | 
|  | 26 | while (--i >= 0) | 
|  | 27 | put_page(rp->pages[i]); | 
|  | 28 | return -ENOMEM; | 
|  | 29 | } | 
|  | 30 |  | 
|  | 31 | static inline void resync_free_pages(struct resync_pages *rp) | 
|  | 32 | { | 
|  | 33 | int i; | 
|  | 34 |  | 
|  | 35 | for (i = 0; i < RESYNC_PAGES; i++) | 
|  | 36 | put_page(rp->pages[i]); | 
|  | 37 | } | 
|  | 38 |  | 
|  | 39 | static inline void resync_get_all_pages(struct resync_pages *rp) | 
|  | 40 | { | 
|  | 41 | int i; | 
|  | 42 |  | 
|  | 43 | for (i = 0; i < RESYNC_PAGES; i++) | 
|  | 44 | get_page(rp->pages[i]); | 
|  | 45 | } | 
|  | 46 |  | 
|  | 47 | static inline struct page *resync_fetch_page(struct resync_pages *rp, | 
|  | 48 | unsigned idx) | 
|  | 49 | { | 
|  | 50 | if (WARN_ON_ONCE(idx >= RESYNC_PAGES)) | 
|  | 51 | return NULL; | 
|  | 52 | return rp->pages[idx]; | 
|  | 53 | } | 
|  | 54 |  | 
|  | 55 | /* | 
|  | 56 | * 'strct resync_pages' stores actual pages used for doing the resync | 
|  | 57 | *  IO, and it is per-bio, so make .bi_private points to it. | 
|  | 58 | */ | 
|  | 59 | static inline struct resync_pages *get_resync_pages(struct bio *bio) | 
|  | 60 | { | 
|  | 61 | return bio->bi_private; | 
|  | 62 | } | 
|  | 63 |  | 
|  | 64 | /* generally called after bio_reset() for reseting bvec */ | 
|  | 65 | static void md_bio_reset_resync_pages(struct bio *bio, struct resync_pages *rp, | 
|  | 66 | int size) | 
|  | 67 | { | 
|  | 68 | int idx = 0; | 
|  | 69 |  | 
|  | 70 | /* initialize bvec table again */ | 
|  | 71 | do { | 
|  | 72 | struct page *page = resync_fetch_page(rp, idx); | 
|  | 73 | int len = min_t(int, size, PAGE_SIZE); | 
|  | 74 |  | 
|  | 75 | /* | 
|  | 76 | * won't fail because the vec table is big | 
|  | 77 | * enough to hold all these pages | 
|  | 78 | */ | 
|  | 79 | bio_add_page(bio, page, len, 0); | 
|  | 80 | size -= len; | 
|  | 81 | } while (idx++ < RESYNC_PAGES && size > 0); | 
|  | 82 | } |