cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

raid1-10.c (2658B)


      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/*
      7 * Number of guaranteed raid bios in case of extreme VM load:
      8 */
      9#define	NR_RAID_BIOS 256
     10
     11/* when we get a read error on a read-only array, we redirect to another
     12 * device without failing the first device, or trying to over-write to
     13 * correct the read error.  To keep track of bad blocks on a per-bio
     14 * level, we store IO_BLOCKED in the appropriate 'bios' pointer
     15 */
     16#define IO_BLOCKED ((struct bio *)1)
     17/* When we successfully write to a known bad-block, we need to remove the
     18 * bad-block marking which must be done from process context.  So we record
     19 * the success by setting devs[n].bio to IO_MADE_GOOD
     20 */
     21#define IO_MADE_GOOD ((struct bio *)2)
     22
     23#define BIO_SPECIAL(bio) ((unsigned long)bio <= 2)
     24
     25/* for managing resync I/O pages */
     26struct resync_pages {
     27	void		*raid_bio;
     28	struct page	*pages[RESYNC_PAGES];
     29};
     30
     31struct raid1_plug_cb {
     32	struct blk_plug_cb	cb;
     33	struct bio_list		pending;
     34};
     35
     36static void rbio_pool_free(void *rbio, void *data)
     37{
     38	kfree(rbio);
     39}
     40
     41static inline int resync_alloc_pages(struct resync_pages *rp,
     42				     gfp_t gfp_flags)
     43{
     44	int i;
     45
     46	for (i = 0; i < RESYNC_PAGES; i++) {
     47		rp->pages[i] = alloc_page(gfp_flags);
     48		if (!rp->pages[i])
     49			goto out_free;
     50	}
     51
     52	return 0;
     53
     54out_free:
     55	while (--i >= 0)
     56		put_page(rp->pages[i]);
     57	return -ENOMEM;
     58}
     59
     60static inline void resync_free_pages(struct resync_pages *rp)
     61{
     62	int i;
     63
     64	for (i = 0; i < RESYNC_PAGES; i++)
     65		put_page(rp->pages[i]);
     66}
     67
     68static inline void resync_get_all_pages(struct resync_pages *rp)
     69{
     70	int i;
     71
     72	for (i = 0; i < RESYNC_PAGES; i++)
     73		get_page(rp->pages[i]);
     74}
     75
     76static inline struct page *resync_fetch_page(struct resync_pages *rp,
     77					     unsigned idx)
     78{
     79	if (WARN_ON_ONCE(idx >= RESYNC_PAGES))
     80		return NULL;
     81	return rp->pages[idx];
     82}
     83
     84/*
     85 * 'strct resync_pages' stores actual pages used for doing the resync
     86 *  IO, and it is per-bio, so make .bi_private points to it.
     87 */
     88static inline struct resync_pages *get_resync_pages(struct bio *bio)
     89{
     90	return bio->bi_private;
     91}
     92
     93/* generally called after bio_reset() for reseting bvec */
     94static void md_bio_reset_resync_pages(struct bio *bio, struct resync_pages *rp,
     95			       int size)
     96{
     97	int idx = 0;
     98
     99	/* initialize bvec table again */
    100	do {
    101		struct page *page = resync_fetch_page(rp, idx);
    102		int len = min_t(int, size, PAGE_SIZE);
    103
    104		/*
    105		 * won't fail because the vec table is big
    106		 * enough to hold all these pages
    107		 */
    108		bio_add_page(bio, page, len, 0);
    109		size -= len;
    110	} while (idx++ < RESYNC_PAGES && size > 0);
    111}