diff options
Diffstat (limited to 'drivers/md/raid1-10.c')
| -rw-r--r-- | drivers/md/raid1-10.c | 81 | 
1 files changed, 81 insertions, 0 deletions
diff --git a/drivers/md/raid1-10.c b/drivers/md/raid1-10.c new file mode 100644 index 000000000000..9f2670b45f31 --- /dev/null +++ b/drivers/md/raid1-10.c @@ -0,0 +1,81 @@ +/* Maximum size of each resync request */ +#define RESYNC_BLOCK_SIZE (64*1024) +#define RESYNC_PAGES ((RESYNC_BLOCK_SIZE + PAGE_SIZE-1) / PAGE_SIZE) + +/* for managing resync I/O pages */ +struct resync_pages { +	void		*raid_bio; +	struct page	*pages[RESYNC_PAGES]; +}; + +static inline int resync_alloc_pages(struct resync_pages *rp, +				     gfp_t gfp_flags) +{ +	int i; + +	for (i = 0; i < RESYNC_PAGES; i++) { +		rp->pages[i] = alloc_page(gfp_flags); +		if (!rp->pages[i]) +			goto out_free; +	} + +	return 0; + +out_free: +	while (--i >= 0) +		put_page(rp->pages[i]); +	return -ENOMEM; +} + +static inline void resync_free_pages(struct resync_pages *rp) +{ +	int i; + +	for (i = 0; i < RESYNC_PAGES; i++) +		put_page(rp->pages[i]); +} + +static inline void resync_get_all_pages(struct resync_pages *rp) +{ +	int i; + +	for (i = 0; i < RESYNC_PAGES; i++) +		get_page(rp->pages[i]); +} + +static inline struct page *resync_fetch_page(struct resync_pages *rp, +					     unsigned idx) +{ +	if (WARN_ON_ONCE(idx >= RESYNC_PAGES)) +		return NULL; +	return rp->pages[idx]; +} + +/* + * 'strct resync_pages' stores actual pages used for doing the resync + *  IO, and it is per-bio, so make .bi_private points to it. + */ +static inline struct resync_pages *get_resync_pages(struct bio *bio) +{ +	return bio->bi_private; +} + +/* generally called after bio_reset() for reseting bvec */ +static void md_bio_reset_resync_pages(struct bio *bio, struct resync_pages *rp, +			       int size) +{ +	int idx = 0; + +	/* initialize bvec table again */ +	do { +		struct page *page = resync_fetch_page(rp, idx); +		int len = min_t(int, size, PAGE_SIZE); + +		/* +		 * won't fail because the vec table is big +		 * enough to hold all these pages +		 */ +		bio_add_page(bio, page, len, 0); +		size -= len; +	} while (idx++ < RESYNC_PAGES && size > 0); +}  |