* device of the previous section.
* Thus there are (near_copies*far_copies) of each chunk, and each is on a different
* drive.
- * near_copies and far_copies must be at least one, and there product is at most
+ * near_copies and far_copies must be at least one, and their product is at most
* raid_disks.
*/
sector_t new_distance, current_distance;
raid10_find_phys(conf, r10_bio);
- spin_lock_irq(&conf->device_lock);
+ rcu_read_lock();
/*
* Check if we can balance. We can balance on the whole
* device if no resync is going on, or below the resync window.
if (disk >= 0 && conf->mirrors[disk].rdev)
atomic_inc(&conf->mirrors[disk].rdev->nr_pending);
- spin_unlock_irq(&conf->device_lock);
+ rcu_read_unlock();
return disk;
}
{
conf_t *conf = mddev_to_conf(mddev);
int i;
- unsigned long flags;
- spin_lock_irqsave(&conf->device_lock, flags);
+ rcu_read_lock();
for (i=0; i<mddev->raid_disks; i++) {
mdk_rdev_t *rdev = conf->mirrors[i].rdev;
- if (rdev && atomic_read(&rdev->nr_pending)) {
+ if (rdev && !rdev->faulty && atomic_read(&rdev->nr_pending)) {
request_queue_t *r_queue = bdev_get_queue(rdev->bdev);
atomic_inc(&rdev->nr_pending);
- spin_unlock_irqrestore(&conf->device_lock, flags);
+ rcu_read_unlock();
if (r_queue->unplug_fn)
r_queue->unplug_fn(r_queue);
- spin_lock_irqsave(&conf->device_lock, flags);
- atomic_dec(&rdev->nr_pending);
+ rdev_dec_pending(rdev, mddev);
+ rcu_read_lock();
}
}
- spin_unlock_irqrestore(&conf->device_lock, flags);
+ rcu_read_unlock();
}
+
static void raid10_unplug(request_queue_t *q)
{
unplug_slaves(q->queuedata);
{
mddev_t *mddev = q->queuedata;
conf_t *conf = mddev_to_conf(mddev);
- unsigned long flags;
int i, ret = 0;
- spin_lock_irqsave(&conf->device_lock, flags);
- for (i=0; i<mddev->raid_disks; i++) {
+ rcu_read_lock();
+ for (i=0; i<mddev->raid_disks && ret == 0; i++) {
mdk_rdev_t *rdev = conf->mirrors[i].rdev;
if (rdev && !rdev->faulty) {
struct block_device *bdev = rdev->bdev;
request_queue_t *r_queue = bdev_get_queue(bdev);
- if (r_queue->issue_flush_fn) {
- ret = r_queue->issue_flush_fn(r_queue, bdev->bd_disk, error_sector);
- if (ret)
- break;
+ if (!r_queue->issue_flush_fn)
+ ret = -EOPNOTSUPP;
+ else {
+ atomic_inc(&rdev->nr_pending);
+ rcu_read_unlock();
+ ret = r_queue->issue_flush_fn(r_queue, bdev->bd_disk,
+ error_sector);
+ rdev_dec_pending(rdev, mddev);
+ rcu_read_lock();
}
}
}
- spin_unlock_irqrestore(&conf->device_lock, flags);
+ rcu_read_unlock();
return ret;
}
* bios[x] to bio
*/
raid10_find_phys(conf, r10_bio);
- spin_lock_irq(&conf->device_lock);
+ rcu_read_lock();
for (i = 0; i < conf->copies; i++) {
int d = r10_bio->devs[i].devnum;
if (conf->mirrors[d].rdev &&
} else
r10_bio->devs[i].bio = NULL;
}
- spin_unlock_irq(&conf->device_lock);
+ rcu_read_unlock();
atomic_set(&r10_bio->remaining, 1);
md_write_start(mddev);
conf_t *conf = mddev->private;
mirror_info_t *tmp;
- spin_lock_irq(&conf->device_lock);
/*
* Find all non-in_sync disks within the RAID10 configuration
* and mark them in_sync
tmp->rdev->in_sync = 1;
}
}
- spin_unlock_irq(&conf->device_lock);
print_conf(conf);
return 0;
* very different from resync
*/
return 0;
- spin_lock_irq(&conf->device_lock);
+
for (mirror=0; mirror < mddev->raid_disks; mirror++)
if ( !(p=conf->mirrors+mirror)->rdev) {
- p->rdev = rdev;
blk_queue_stack_limits(mddev->queue,
rdev->bdev->bd_disk->queue);
p->head_position = 0;
rdev->raid_disk = mirror;
found = 1;
+ p->rdev = rdev;
break;
}
- spin_unlock_irq(&conf->device_lock);
print_conf(conf);
return found;
static int raid10_remove_disk(mddev_t *mddev, int number)
{
conf_t *conf = mddev->private;
- int err = 1;
+ int err = 0;
+ mdk_rdev_t *rdev;
mirror_info_t *p = conf->mirrors+ number;
print_conf(conf);
- spin_lock_irq(&conf->device_lock);
- if (p->rdev) {
- if (p->rdev->in_sync ||
- atomic_read(&p->rdev->nr_pending)) {
+ rdev = p->rdev;
+ if (rdev) {
+ if (rdev->in_sync ||
+ atomic_read(&rdev->nr_pending)) {
err = -EBUSY;
goto abort;
}
p->rdev = NULL;
- err = 0;
+ synchronize_kernel();
+ if (atomic_read(&rdev->nr_pending)) {
+ /* lost the race, try later */
+ err = -EBUSY;
+ p->rdev = rdev;
+ }
}
- if (err)
- MD_BUG();
abort:
- spin_unlock_irq(&conf->device_lock);
print_conf(conf);
return err;
atomic_inc(&r10_bio->remaining);
md_sync_acct(conf->mirrors[d].rdev->bdev, tbio->bi_size >> 9);
+ tbio->bi_sector += conf->mirrors[d].rdev->data_offset;
+ tbio->bi_bdev = conf->mirrors[d].rdev->bdev;
generic_make_request(tbio);
}
int mirror;
bio = r10_bio->devs[r10_bio->read_slot].bio;
r10_bio->devs[r10_bio->read_slot].bio = NULL;
+ bio_put(bio);
mirror = read_balance(conf, r10_bio);
- r10_bio->devs[r10_bio->read_slot].bio = bio;
if (mirror == -1) {
printk(KERN_ALERT "raid10: %s: unrecoverable I/O"
" read error for block %llu\n",
" another mirror\n",
bdevname(rdev->bdev,b),
(unsigned long long)r10_bio->sector);
- bio->bi_bdev = rdev->bdev;
+ bio = bio_clone(r10_bio->master_bio, GFP_NOIO);
+ r10_bio->devs[r10_bio->read_slot].bio = bio;
bio->bi_sector = r10_bio->devs[r10_bio->read_slot].addr
+ rdev->data_offset;
- bio->bi_next = NULL;
- bio->bi_flags &= (1<<BIO_CLONED);
- bio->bi_flags |= 1 << BIO_UPTODATE;
- bio->bi_idx = 0;
- bio->bi_size = r10_bio->sectors << 9;
+ bio->bi_bdev = rdev->bdev;
bio->bi_rw = READ;
+ bio->bi_private = r10_bio;
+ bio->bi_end_io = raid10_end_read_request;
unplug = 1;
generic_make_request(bio);
}
* put in a delay to throttle resync.
*/
if (!go_faster && waitqueue_active(&conf->wait_resume))
- schedule_timeout(HZ);
+ msleep_interruptible(1000);
device_barrier(conf, sector_nr + RESYNC_SECTORS);
/* Again, very different code for resync and recovery.
set_bit(R10BIO_IsSync, &r10_bio->state);
raid10_find_phys(conf, r10_bio);
r10_bio->sectors = (sector_nr | conf->chunk_mask) - sector_nr +1;
- spin_lock_irq(&conf->device_lock);
+
for (i=0; i<conf->copies; i++) {
int d = r10_bio->devs[i].devnum;
bio = r10_bio->devs[i].bio;
bio->bi_bdev = conf->mirrors[d].rdev->bdev;
count++;
}
- spin_unlock_irq(&conf->device_lock);
+
if (count < 2) {
for (i=0; i<conf->copies; i++) {
int d = r10_bio->devs[i].devnum;
if (r10_bio->devs[i].bio->bi_end_io)
- atomic_dec(&conf->mirrors[d].rdev->nr_pending);
+ rdev_dec_pending(conf->mirrors[d].rdev, mddev);
}
put_buf(r10_bio);
+ biolist = NULL;
goto giveup;
}
}
}
}
- return nr_sectors;
+ return sectors_skipped + nr_sectors;
giveup:
/* There is nowhere to write, so all non-sync
* drives must be failed, so try the next chunk...
}
conf->raid_disks = mddev->raid_disks;
conf->mddev = mddev;
- conf->device_lock = SPIN_LOCK_UNLOCKED;
+ spin_lock_init(&conf->device_lock);
INIT_LIST_HEAD(&conf->retry_list);
- conf->resync_lock = SPIN_LOCK_UNLOCKED;
+ spin_lock_init(&conf->resync_lock);
init_waitqueue_head(&conf->wait_idle);
init_waitqueue_head(&conf->wait_resume);
md_unregister_thread(mddev->thread);
mddev->thread = NULL;
+ blk_sync_queue(mddev->queue); /* the unplug fn references 'conf'*/
if (conf->r10bio_pool)
mempool_destroy(conf->r10bio_pool);
if (conf->mirrors)