/* * raid5.c : Multiple Devices driver for Linux * Copyright (C) 1996, 1997 Ingo Molnar, Miguel de Icaza, Gadi Oxman * Copyright (C) 1999, 2000 Ingo Molnar * Copyright (C) 2002, 2003 H. Peter Anvin * * RAID-4/5/6 management functions. * Thanks to Penguin Computing for making the RAID-6 development possible * by donating a test server! * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * You should have received a copy of the GNU General Public License * (for example /usr/src/linux/COPYING); if not, write to the Free * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ /* * BITMAP UNPLUGGING: * * The sequencing for updating the bitmap reliably is a little * subtle (and I got it wrong the first time) so it deserves some * explanation. * * We group bitmap updates into batches. Each batch has a number. * We may write out several batches at once, but that isn't very important. * conf->seq_write is the number of the last batch successfully written. * conf->seq_flush is the number of the last batch that was closed to * new additions. * When we discover that we will need to write to any block in a stripe * (in add_stripe_bio) we update the in-memory bitmap and record in sh->bm_seq * the number of the batch it will be in. This is seq_flush+1. * When we are ready to do a write, if that batch hasn't been written yet, * we plug the array and queue the stripe for later. * When an unplug happens, we increment bm_flush, thus closing the current * batch. * When we notice that bm_flush > bm_write, we write out all pending updates * to the bitmap, and advance bm_write to where bm_flush was. * This may occasionally write a bit out twice, but is sure never to * miss any bits. */ #include <linux/blkdev.h>#include <linux/kthread.h>#include <linux/raid/pq.h>#include <linux/async_tx.h>#include <linux/module.h>#include <linux/async.h>#include <linux/seq_file.h>#include <linux/cpu.h>#include <linux/slab.h>#include <linux/ratelimit.h>#include "md.h"#include "raid5.h"#include "raid0.h"#include "bitmap.h" /* * Stripe cache */ #define NR_STRIPES 256#define STRIPE_SIZE PAGE_SIZE#define STRIPE_SHIFT (PAGE_SHIFT - 9)#define STRIPE_SECTORS (STRIPE_SIZE>>9)#define IO_THRESHOLD 1#define BYPASS_THRESHOLD 1#define NR_HASH (PAGE_SIZE / sizeof(struct hlist_head))#define HASH_MASK (NR_HASH - 1) static inline struct hlist_head *stripe_hash(struct r5conf *conf, sector_t sect){ int hash = (sect >> STRIPE_SHIFT) & HASH_MASK; return &conf->stripe_hashtbl[hash];} /* bio's attached to a stripe+device for I/O are linked together in bi_sector * order without overlap. There may be several bio's per stripe+device, and * a bio could span several devices. * When walking this list for a particular stripe+device, we must never proceed * beyond a bio that extends past this device, as the next bio might no longer * be valid. * This function is used to determine the 'next' bio in the list, given the sector * of the current stripe+device */static inline struct bio *r5_next_bio(struct bio *bio, sector_t sector){ int sectors = bio->bi_size >> 9; if (bio->bi_sector + sectors < sector + STRIPE_SECTORS) return bio->bi_next; else return NULL;} /* * We maintain a biased count of active stripes in the bottom 16 bits of * bi_phys_segments, and a count of processed stripes in the upper 16 bits */static inline int raid5_bi_phys_segments(struct bio *bio){ return bio->bi_phys_segments & 0xffff;} static inline int raid5_bi_hw_segments(struct bio *bio){ return (bio->bi_phys_segments >> 16) & 0xffff;} static inline int raid5_dec_bi_phys_segments(struct bio *bio){ --bio->bi_phys_segments; return raid5_bi_phys_segments(bio);} static inline int raid5_dec_bi_hw_segments(struct bio *bio){ unsigned short val = raid5_bi_hw_segments(bio); --val; bio->bi_phys_segments = (val << 16) | raid5_bi_phys_segments(bio); return val;} static inline void raid5_set_bi_hw_segments(struct bio *bio, unsigned int cnt){ bio->bi_phys_segments = raid5_bi_phys_segments(bio) | (cnt << 16);} /* Find first data disk in a raid6 stripe */static inline int raid6_d0(struct stripe_head *sh){ if (sh->ddf_layout) /* ddf always start from first device */ return 0; /* md starts just after Q block */ if (sh->qd_idx == sh->disks - 1) return 0; else return sh->qd_idx + 1;}static inline int raid6_next_disk(int disk, int raid_disks){ disk++; return (disk < raid_disks) ? disk : 0;} /* When walking through the disks in a raid5, starting at raid6_d0, * We need to map each disk to a 'slot', where the data disks are slot * 0 .. raid_disks-3, the parity disk is raid_disks-2 and the Q disk * is raid_disks-1. This help does that mapping. */static int raid6_idx_to_slot(int idx, struct stripe_head *sh, int *count, int syndrome_disks){ int slot = *count; if (sh->ddf_layout) (*count)++; if (idx == sh->pd_idx) return syndrome_disks; if (idx == sh->qd_idx) return syndrome_disks + 1; if (!sh->ddf_layout) (*count)++; return slot;} static void return_io(struct bio *return_bi){ struct bio *bi = return_bi; while (bi) { return_bi = bi->bi_next; bi->bi_next = NULL; bi->bi_size = 0; bio_endio(bi, 0); bi = return_bi; }} static void print_raid5_conf (struct r5conf *conf); static int stripe_operations_active(struct stripe_head *sh){ return sh->check_state || sh->reconstruct_state || test_bit(STRIPE_BIOFILL_RUN, &sh->state) || test_bit(STRIPE_COMPUTE_RUN, &sh->state);} static void __release_stripe(struct r5conf *conf, struct stripe_head *sh){ if (atomic_dec_and_test(&sh->count)) { BUG_ON(!list_empty(&sh->lru)); BUG_ON(atomic_read(&conf->active_stripes)==0); if (test_bit(STRIPE_HANDLE, &sh->state)) { if (test_bit(STRIPE_DELAYED, &sh->state)) list_add_tail(&sh->lru, &conf->delayed_list); else if (test_bit(STRIPE_BIT_DELAY, &sh->state) && sh->bm_seq - conf->seq_write > 0) list_add_tail(&sh->lru, &conf->bitmap_list); else { clear_bit(STRIPE_BIT_DELAY, &sh->state); list_add_tail(&sh->lru, &conf->handle_list); } md_wakeup_thread(conf->mddev->thread); } else { BUG_ON(stripe_operations_active(sh)); if (test_and_clear_bit(STRIPE_PREREAD_ACTIVE, &sh->state)) if (atomic_dec_return(&conf->preread_active_stripes) < IO_THRESHOLD) md_wakeup_thread(conf->mddev->thread); atomic_dec(&conf->active_stripes); if (!test_bit(STRIPE_EXPANDING, &sh->state)) { list_add_tail(&sh->lru, &conf->inactive_list); wake_up(&conf->wait_for_stripe); if (conf->retry_read_aligned) md_wakeup_thread(conf->mddev->thread); } } }} static void release_stripe(struct stripe_head *sh){ struct r5conf *conf = sh->raid_conf; unsigned long flags; spin_lock_irqsave(&conf->device_lock, flags); __release_stripe(conf, sh); spin_unlock_irqrestore(&conf->device_lock, flags);} static inline void remove_hash(struct stripe_head *sh){ pr_debug("remove_hash(), stripe %llu\n", (unsigned long long)sh->sector); hlist_del_init(&sh->hash);} static inline void insert_hash(struct r5conf *conf, struct stripe_head *sh){ struct hlist_head *hp = stripe_hash(conf, sh->sector); pr_debug("insert_hash(), stripe %llu\n", (unsigned long long)sh->sector); hlist_add_head(&sh->hash, hp);} /* find an idle stripe, make sure it is unhashed, and return it. */static struct stripe_head *get_free_stripe(struct r5conf *conf){ struct stripe_head *sh = NULL; struct list_head *first; if (list_empty(&conf->inactive_list)) goto out; first = conf->inactive_list.next; sh = list_entry(first, struct stripe_head, lru); list_del_init(first); remove_hash(sh); atomic_inc(&conf->active_stripes);out: return sh;} static void shrink_buffers(struct stripe_head *sh){ struct page *p; int i; int num = sh->raid_conf->pool_size; for (i = 0; i < num ; i++) { p = sh->dev[i].page; if (!p) continue; sh->dev[i].page = NULL; put_page(p); }} static int grow_buffers(struct stripe_head *sh){ int i; int num = sh->raid_conf->pool_size; for (i = 0; i < num; i++) { struct page *page; if (!(page = alloc_page(GFP_KERNEL))) { return 1; } sh->dev[i].page = page; } return 0;} static void raid5_build_block(struct stripe_head *sh, int i, int previous);static void stripe_set_idx(sector_t stripe, struct r5conf *conf, int previous, struct stripe_head *sh); static void init_stripe(struct stripe_head *sh, sector_t sector, int previous){ struct r5conf *conf = sh->raid_conf; int i; BUG_ON(atomic_read(&sh->count) != 0); BUG_ON(test_bit(STRIPE_HANDLE, &sh->state)); BUG_ON(stripe_operations_active(sh)); pr_debug("init_stripe called, stripe %llu\n", (unsigned long long)sh->sector); remove_hash(sh); sh->generation = conf->generation - previous; sh->disks = previous ? conf->previous_raid_disks : conf->raid_disks; sh->sector = sector; stripe_set_idx(sector, conf, previous, sh); sh->state = 0; for (i = sh->disks; i--; ) { struct r5dev *dev = &sh->dev[i]; if (dev->toread || dev->read || dev->towrite || dev->written || test_bit(R5_LOCKED, &dev->flags)) { printk(KERN_ERR "sector=%llx i=%d %p %p %p %p %d\n", (unsigned long long)sh->sector, i, dev->toread, dev->read, dev->towrite, dev->written, test_bit(R5_LOCKED, &dev->flags)); WARN_ON(1); } dev->flags = 0; raid5_build_block(sh, i, previous); } insert_hash(conf, sh);} static struct stripe_head *__find_stripe(struct r5conf *conf, sector_t sector, short generation){ struct stripe_head *sh; struct hlist_node *hn; pr_debug("__find_stripe, sector %llu\n", (unsigned long long)sector); hlist_for_each_entry(sh, hn, stripe_hash(conf, sector), hash) if (sh->sector == sector && sh->generation == generation) return sh; pr_debug("__stripe %llu not in cache\n", (unsigned long long)sector); return NULL;} /* * Need to check if array has failed when deciding whether to: * - start an array * - remove non-faulty devices * - add a spare * - allow a reshape * This determination is simple when no reshape is happening. * However if there is a reshape, we need to carefully check * both the before and after sections. * This is because some failed devices may only affect one * of the two sections, and some non-in_sync devices may * be insync in the section most affected by failed devices. */static int calc_degraded(struct r5conf *conf){ int degraded, degraded2; int i; rcu_read_lock(); degraded = 0; for (i = 0; i < conf->previous_raid_disks; i++) { struct md_rdev *rdev = rcu_dereference(conf->disks[i].rdev); if (!rdev || test_bit(Faulty, &rdev->flags)) degraded++; else if (test_bit(In_sync, &rdev->flags)) ; else /* not in-sync or faulty. * If the reshape increases the number of devices, * this is being recovered by the reshape, so * this 'previous' section is not in_sync. * If the number of devices is being reduced however, * the device can only be part of the array if * we are reverting a reshape, so this section will * be in-sync. */ if (conf->raid_disks >= conf->previous_raid_disks) degraded++; } rcu_read_unlock(); if (conf->raid_disks == conf->previous_raid_disks) return degraded; rcu_read_lock(); degraded2 = 0; for (i = 0; i < conf->raid_disks; i++) { struct md_rdev *rdev = rcu_dereference(conf->disks[i].rdev); if (!rdev || test_bit(Faulty, &rdev->flags)) degraded2++; else if (test_bit(In_sync, &rdev->flags)) ; else /* not in-sync or faulty. * If reshape increases the number of devices, this * section has already been recovered, else it * almost certainly hasn't. */ if (conf->raid_disks <= conf->previous_raid_disks) degraded2++; } rcu_read_unlock(); if (degraded2 > degraded) return degraded2; return degraded;} static int has_failed(struct r5conf *conf){ int degraded; if (conf->mddev->reshape_position == MaxSector) return conf->mddev->degraded > conf->max_degraded; degraded = calc_degraded(conf); if (degraded > conf->max_degraded) return 1; return 0;} static struct stripe_head *get_active_stripe(struct r5conf *conf, sector_t sector, int previous, int noblock, int noquiesce){ struct stripe_head *sh; pr_debug("get_stripe, sector %llu\n", (unsigned long long)sector); spin_lock_irq(&conf->device_lock); do { wait_event_lock_irq(conf->wait_for_stripe, conf->quiesce == 0 || noquiesce, conf->device_lock, /* nothing */); sh = __find_stripe(conf, sector, conf->generation - previous); if (!sh) { if (!conf->inactive_blocked) sh = get_free_stripe(conf); if (noblock && sh == NULL) break; if (!sh) { conf->inactive_blocked = 1; wait_event_lock_irq(conf->wait_for_stripe, !list_empty(&conf->inactive_list) && (atomic_read(&conf->active_stripes) < (conf->max_nr_stripes *3/4) || !conf->inactive_blocked), conf->device_lock, ); conf->inactive_blocked = 0; } else init_stripe(sh, sector, previous); } else { if (atomic_read(&sh->count)) { BUG_ON(!list_empty(&sh->lru) && !test_bit(STRIPE_EXPANDING, &sh->state)); } else { if (!test_bit(STRIPE_HANDLE, &sh->state)) atomic_inc(&conf->active_stripes); if (list_empty(&sh->lru) && !test_bit(STRIPE_EXPANDING, &sh->state)) BUG(); list_del_init(&sh->lru); } } } while (sh == NULL); if (sh) atomic_inc(&sh->count); spin_unlock_irq(&conf->device_lock); return sh;} /* Determine if 'data_offset' or 'new_data_offset' should be used * in this stripe_head. */static int use_new_offset(struct r5conf *conf, struct stripe_head *sh){ sector_t progress = conf->reshape_progress; /* Need a memory barrier to make sure we see the value * of conf->generation, or ->data_offset that was set before * reshape_progress was updated. */Lines 1–500 of 6144. Load more
/* * raid5.c : Multiple Devices driver for Linux * Copyright (C) 1996, 1997 Ingo Molnar, Miguel de Icaza, Gadi Oxman * Copyright (C) 1999, 2000 Ingo Molnar * Copyright (C) 2002, 2003 H. Peter Anvin * * RAID-4/5/6 management functions. * Thanks to Penguin Computing for making the RAID-6 development possible * by donating a test server! * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * You should have received a copy of the GNU General Public License * (for example /usr/src/linux/COPYING); if not, write to the Free * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ /* * BITMAP UNPLUGGING: * * The sequencing for updating the bitmap reliably is a little * subtle (and I got it wrong the first time) so it deserves some * explanation. * * We group bitmap updates into batches. Each batch has a number. * We may write out several batches at once, but that isn't very important. * conf->seq_write is the number of the last batch successfully written. * conf->seq_flush is the number of the last batch that was closed to * new additions. * When we discover that we will need to write to any block in a stripe * (in add_stripe_bio) we update the in-memory bitmap and record in sh->bm_seq * the number of the batch it will be in. This is seq_flush+1. * When we are ready to do a write, if that batch hasn't been written yet, * we plug the array and queue the stripe for later. * When an unplug happens, we increment bm_flush, thus closing the current * batch. * When we notice that bm_flush > bm_write, we write out all pending updates * to the bitmap, and advance bm_write to where bm_flush was. * This may occasionally write a bit out twice, but is sure never to * miss any bits. */ #include <linux/blkdev.h> #include <linux/kthread.h> #include <linux/raid/pq.h> #include <linux/async_tx.h> #include <linux/module.h> #include <linux/async.h> #include <linux/seq_file.h> #include <linux/cpu.h> #include <linux/slab.h> #include <linux/ratelimit.h> #include "md.h" #include "raid5.h" #include "raid0.h" #include "bitmap.h" /* * Stripe cache */ #define NR_STRIPES 256 #define STRIPE_SIZE PAGE_SIZE #define STRIPE_SHIFT (PAGE_SHIFT - 9) #define STRIPE_SECTORS (STRIPE_SIZE>>9) #define IO_THRESHOLD 1 #define BYPASS_THRESHOLD 1 #define NR_HASH (PAGE_SIZE / sizeof(struct hlist_head)) #define HASH_MASK (NR_HASH - 1) static inline struct hlist_head *stripe_hash(struct r5conf *conf, sector_t sect) { int hash = (sect >> STRIPE_SHIFT) & HASH_MASK; return &conf->stripe_hashtbl[hash]; } /* bio's attached to a stripe+device for I/O are linked together in bi_sector * order without overlap. There may be several bio's per stripe+device, and * a bio could span several devices. * When walking this list for a particular stripe+device, we must never proceed * beyond a bio that extends past this device, as the next bio might no longer * be valid. * This function is used to determine the 'next' bio in the list, given the sector * of the current stripe+device */ static inline struct bio *r5_next_bio(struct bio *bio, sector_t sector) { int sectors = bio->bi_size >> 9; if (bio->bi_sector + sectors < sector + STRIPE_SECTORS) return bio->bi_next; else return NULL; } /* * We maintain a biased count of active stripes in the bottom 16 bits of * bi_phys_segments, and a count of processed stripes in the upper 16 bits */ static inline int raid5_bi_phys_segments(struct bio *bio) { return bio->bi_phys_segments & 0xffff; } static inline int raid5_bi_hw_segments(struct bio *bio) { return (bio->bi_phys_segments >> 16) & 0xffff; } static inline int raid5_dec_bi_phys_segments(struct bio *bio) { --bio->bi_phys_segments; return raid5_bi_phys_segments(bio); } static inline int raid5_dec_bi_hw_segments(struct bio *bio) { unsigned short val = raid5_bi_hw_segments(bio); --val; bio->bi_phys_segments = (val << 16) | raid5_bi_phys_segments(bio); return val; } static inline void raid5_set_bi_hw_segments(struct bio *bio, unsigned int cnt) { bio->bi_phys_segments = raid5_bi_phys_segments(bio) | (cnt << 16); } /* Find first data disk in a raid6 stripe */ static inline int raid6_d0(struct stripe_head *sh) { if (sh->ddf_layout) /* ddf always start from first device */ return 0; /* md starts just after Q block */ if (sh->qd_idx == sh->disks - 1) return 0; else return sh->qd_idx + 1; } static inline int raid6_next_disk(int disk, int raid_disks) { disk++; return (disk < raid_disks) ? disk : 0; } /* When walking through the disks in a raid5, starting at raid6_d0, * We need to map each disk to a 'slot', where the data disks are slot * 0 .. raid_disks-3, the parity disk is raid_disks-2 and the Q disk * is raid_disks-1. This help does that mapping. */ static int raid6_idx_to_slot(int idx, struct stripe_head *sh, int *count, int syndrome_disks) { int slot = *count; if (sh->ddf_layout) (*count)++; if (idx == sh->pd_idx) return syndrome_disks; if (idx == sh->qd_idx) return syndrome_disks + 1; if (!sh->ddf_layout) (*count)++; return slot; } static void return_io(struct bio *return_bi) { struct bio *bi = return_bi; while (bi) { return_bi = bi->bi_next; bi->bi_next = NULL; bi->bi_size = 0; bio_endio(bi, 0); bi = return_bi; } } static void print_raid5_conf (struct r5conf *conf); static int stripe_operations_active(struct stripe_head *sh) { return sh->check_state || sh->reconstruct_state || test_bit(STRIPE_BIOFILL_RUN, &sh->state) || test_bit(STRIPE_COMPUTE_RUN, &sh->state); } static void __release_stripe(struct r5conf *conf, struct stripe_head *sh) { if (atomic_dec_and_test(&sh->count)) { BUG_ON(!list_empty(&sh->lru)); BUG_ON(atomic_read(&conf->active_stripes)==0); if (test_bit(STRIPE_HANDLE, &sh->state)) { if (test_bit(STRIPE_DELAYED, &sh->state)) list_add_tail(&sh->lru, &conf->delayed_list); else if (test_bit(STRIPE_BIT_DELAY, &sh->state) && sh->bm_seq - conf->seq_write > 0) list_add_tail(&sh->lru, &conf->bitmap_list); else { clear_bit(STRIPE_BIT_DELAY, &sh->state); list_add_tail(&sh->lru, &conf->handle_list); } md_wakeup_thread(conf->mddev->thread); } else { BUG_ON(stripe_operations_active(sh)); if (test_and_clear_bit(STRIPE_PREREAD_ACTIVE, &sh->state)) if (atomic_dec_return(&conf->preread_active_stripes) < IO_THRESHOLD) md_wakeup_thread(conf->mddev->thread); atomic_dec(&conf->active_stripes); if (!test_bit(STRIPE_EXPANDING, &sh->state)) { list_add_tail(&sh->lru, &conf->inactive_list); wake_up(&conf->wait_for_stripe); if (conf->retry_read_aligned) md_wakeup_thread(conf->mddev->thread); } } } } static void release_stripe(struct stripe_head *sh) { struct r5conf *conf = sh->raid_conf; unsigned long flags; spin_lock_irqsave(&conf->device_lock, flags); __release_stripe(conf, sh); spin_unlock_irqrestore(&conf->device_lock, flags); } static inline void remove_hash(struct stripe_head *sh) { pr_debug("remove_hash(), stripe %llu\n", (unsigned long long)sh->sector); hlist_del_init(&sh->hash); } static inline void insert_hash(struct r5conf *conf, struct stripe_head *sh) { struct hlist_head *hp = stripe_hash(conf, sh->sector); pr_debug("insert_hash(), stripe %llu\n", (unsigned long long)sh->sector); hlist_add_head(&sh->hash, hp); } /* find an idle stripe, make sure it is unhashed, and return it. */ static struct stripe_head *get_free_stripe(struct r5conf *conf) { struct stripe_head *sh = NULL; struct list_head *first; if (list_empty(&conf->inactive_list)) goto out; first = conf->inactive_list.next; sh = list_entry(first, struct stripe_head, lru); list_del_init(first); remove_hash(sh); atomic_inc(&conf->active_stripes); out: return sh; } static void shrink_buffers(struct stripe_head *sh) { struct page *p; int i; int num = sh->raid_conf->pool_size; for (i = 0; i < num ; i++) { p = sh->dev[i].page; if (!p) continue; sh->dev[i].page = NULL; put_page(p); } } static int grow_buffers(struct stripe_head *sh) { int i; int num = sh->raid_conf->pool_size; for (i = 0; i < num; i++) { struct page *page; if (!(page = alloc_page(GFP_KERNEL))) { return 1; } sh->dev[i].page = page; } return 0; } static void raid5_build_block(struct stripe_head *sh, int i, int previous); static void stripe_set_idx(sector_t stripe, struct r5conf *conf, int previous, struct stripe_head *sh); static void init_stripe(struct stripe_head *sh, sector_t sector, int previous) { struct r5conf *conf = sh->raid_conf; int i; BUG_ON(atomic_read(&sh->count) != 0); BUG_ON(test_bit(STRIPE_HANDLE, &sh->state)); BUG_ON(stripe_operations_active(sh)); pr_debug("init_stripe called, stripe %llu\n", (unsigned long long)sh->sector); remove_hash(sh); sh->generation = conf->generation - previous; sh->disks = previous ? conf->previous_raid_disks : conf->raid_disks; sh->sector = sector; stripe_set_idx(sector, conf, previous, sh); sh->state = 0; for (i = sh->disks; i--; ) { struct r5dev *dev = &sh->dev[i]; if (dev->toread || dev->read || dev->towrite || dev->written || test_bit(R5_LOCKED, &dev->flags)) { printk(KERN_ERR "sector=%llx i=%d %p %p %p %p %d\n", (unsigned long long)sh->sector, i, dev->toread, dev->read, dev->towrite, dev->written, test_bit(R5_LOCKED, &dev->flags)); WARN_ON(1); } dev->flags = 0; raid5_build_block(sh, i, previous); } insert_hash(conf, sh); } static struct stripe_head *__find_stripe(struct r5conf *conf, sector_t sector, short generation) { struct stripe_head *sh; struct hlist_node *hn; pr_debug("__find_stripe, sector %llu\n", (unsigned long long)sector); hlist_for_each_entry(sh, hn, stripe_hash(conf, sector), hash) if (sh->sector == sector && sh->generation == generation) return sh; pr_debug("__stripe %llu not in cache\n", (unsigned long long)sector); return NULL; } /* * Need to check if array has failed when deciding whether to: * - start an array * - remove non-faulty devices * - add a spare * - allow a reshape * This determination is simple when no reshape is happening. * However if there is a reshape, we need to carefully check * both the before and after sections. * This is because some failed devices may only affect one * of the two sections, and some non-in_sync devices may * be insync in the section most affected by failed devices. */ static int calc_degraded(struct r5conf *conf) { int degraded, degraded2; int i; rcu_read_lock(); degraded = 0; for (i = 0; i < conf->previous_raid_disks; i++) { struct md_rdev *rdev = rcu_dereference(conf->disks[i].rdev); if (!rdev || test_bit(Faulty, &rdev->flags)) degraded++; else if (test_bit(In_sync, &rdev->flags)) ; else /* not in-sync or faulty. * If the reshape increases the number of devices, * this is being recovered by the reshape, so * this 'previous' section is not in_sync. * If the number of devices is being reduced however, * the device can only be part of the array if * we are reverting a reshape, so this section will * be in-sync. */ if (conf->raid_disks >= conf->previous_raid_disks) degraded++; } rcu_read_unlock(); if (conf->raid_disks == conf->previous_raid_disks) return degraded; rcu_read_lock(); degraded2 = 0; for (i = 0; i < conf->raid_disks; i++) { struct md_rdev *rdev = rcu_dereference(conf->disks[i].rdev); if (!rdev || test_bit(Faulty, &rdev->flags)) degraded2++; else if (test_bit(In_sync, &rdev->flags)) ; else /* not in-sync or faulty. * If reshape increases the number of devices, this * section has already been recovered, else it * almost certainly hasn't. */ if (conf->raid_disks <= conf->previous_raid_disks) degraded2++; } rcu_read_unlock(); if (degraded2 > degraded) return degraded2; return degraded; } static int has_failed(struct r5conf *conf) { int degraded; if (conf->mddev->reshape_position == MaxSector) return conf->mddev->degraded > conf->max_degraded; degraded = calc_degraded(conf); if (degraded > conf->max_degraded) return 1; return 0; } static struct stripe_head * get_active_stripe(struct r5conf *conf, sector_t sector, int previous, int noblock, int noquiesce) { struct stripe_head *sh; pr_debug("get_stripe, sector %llu\n", (unsigned long long)sector); spin_lock_irq(&conf->device_lock); do { wait_event_lock_irq(conf->wait_for_stripe, conf->quiesce == 0 || noquiesce, conf->device_lock, /* nothing */); sh = __find_stripe(conf, sector, conf->generation - previous); if (!sh) { if (!conf->inactive_blocked) sh = get_free_stripe(conf); if (noblock && sh == NULL) break; if (!sh) { conf->inactive_blocked = 1; wait_event_lock_irq(conf->wait_for_stripe, !list_empty(&conf->inactive_list) && (atomic_read(&conf->active_stripes) < (conf->max_nr_stripes *3/4) || !conf->inactive_blocked), conf->device_lock, ); conf->inactive_blocked = 0; } else init_stripe(sh, sector, previous); } else { if (atomic_read(&sh->count)) { BUG_ON(!list_empty(&sh->lru) && !test_bit(STRIPE_EXPANDING, &sh->state)); } else { if (!test_bit(STRIPE_HANDLE, &sh->state)) atomic_inc(&conf->active_stripes); if (list_empty(&sh->lru) && !test_bit(STRIPE_EXPANDING, &sh->state)) BUG(); list_del_init(&sh->lru); } } } while (sh == NULL); if (sh) atomic_inc(&sh->count); spin_unlock_irq(&conf->device_lock); return sh; } /* Determine if 'data_offset' or 'new_data_offset' should be used * in this stripe_head. */ static int use_new_offset(struct r5conf *conf, struct stripe_head *sh) { sector_t progress = conf->reshape_progress; /* Need a memory barrier to make sure we see the value * of conf->generation, or ->data_offset that was set before * reshape_progress was updated. */