#include <linux/module.h>
#include <linux/slab.h>
#include <linux/highmem.h>
-#include <linux/bitops.h>
+#include <asm/bitops.h>
#include <asm/atomic.h>
#include "raid6.h"
case READ_MODIFY_WRITE:
BUG(); /* READ_MODIFY_WRITE N/A for RAID-6 */
case RECONSTRUCT_WRITE:
+ case UPDATE_PARITY: /* Is this right? */
for (i= disks; i-- ;)
if ( i != pd_idx && i != qd_idx && sh->dev[i].towrite ) {
chosen = sh->dev[i].towrite;
i = d0_idx;
do {
ptrs[count++] = page_address(sh->dev[i].page);
- if (count <= disks-2 && !test_bit(R5_UPTODATE, &sh->dev[i].flags))
- printk("block %d/%d not uptodate on parity calc\n", i,count);
+
i = raid6_next_disk(i, disks);
} while ( i != d0_idx );
// break;
if (test_bit(R5_UPTODATE, &sh->dev[i].flags))
ptr[count++] = p;
else
- printk("compute_block() %d, stripe %llu, %d"
+ PRINTK("compute_block() %d, stripe %llu, %d"
" not present\n", dd_idx,
(unsigned long long)sh->sector, i);
do {
ptrs[count++] = page_address(sh->dev[i].page);
i = raid6_next_disk(i, disks);
- if (i != dd_idx1 && i != dd_idx2 &&
- !test_bit(R5_UPTODATE, &sh->dev[i].flags))
- printk("compute_2 with missing block %d/%d\n", count, i);
} while ( i != d0_idx );
if ( failb == disks-2 ) {
* parity, or to satisfy requests
* or to load a block that is being partially written.
*/
- if (to_read || non_overwrite || (to_write && failed) || (syncing && (uptodate < disks))) {
+ if (to_read || non_overwrite || (syncing && (uptodate < disks))) {
for (i=disks; i--;) {
dev = &sh->dev[i];
if (!test_bit(R5_LOCKED, &dev->flags) && !test_bit(R5_UPTODATE, &dev->flags) &&
(dev->toread ||
(dev->towrite && !test_bit(R5_OVERWRITE, &dev->flags)) ||
syncing ||
- (failed >= 1 && (sh->dev[failed_num[0]].toread || to_write)) ||
- (failed >= 2 && (sh->dev[failed_num[1]].toread || to_write))
+ (failed >= 1 && (sh->dev[failed_num[0]].toread ||
+ (sh->dev[failed_num[0]].towrite && !test_bit(R5_OVERWRITE, &sh->dev[failed_num[0]].flags)))) ||
+ (failed >= 2 && (sh->dev[failed_num[1]].toread ||
+ (sh->dev[failed_num[1]].towrite && !test_bit(R5_OVERWRITE, &sh->dev[failed_num[1]].flags))))
)
) {
/* we would like to get this block, possibly
else
bi->bi_end_io = raid6_end_read_request;
- rcu_read_lock();
+ spin_lock_irq(&conf->device_lock);
rdev = conf->disks[i].rdev;
if (rdev && rdev->faulty)
rdev = NULL;
if (rdev)
atomic_inc(&rdev->nr_pending);
- rcu_read_unlock();
+ spin_unlock_irq(&conf->device_lock);
if (rdev) {
if (test_bit(R5_Syncio, &sh->dev[i].flags))
{
raid6_conf_t *conf = mddev_to_conf(mddev);
int i;
+ unsigned long flags;
- rcu_read_lock();
+ spin_lock_irqsave(&conf->device_lock, flags);
for (i=0; i<mddev->raid_disks; i++) {
mdk_rdev_t *rdev = conf->disks[i].rdev;
- if (rdev && !rdev->faulty && atomic_read(&rdev->nr_pending)) {
+ if (rdev && atomic_read(&rdev->nr_pending)) {
request_queue_t *r_queue = bdev_get_queue(rdev->bdev);
atomic_inc(&rdev->nr_pending);
- rcu_read_unlock();
+ spin_unlock_irqrestore(&conf->device_lock, flags);
- if (r_queue->unplug_fn)
+ if (r_queue && r_queue->unplug_fn)
r_queue->unplug_fn(r_queue);
+ spin_lock_irqsave(&conf->device_lock, flags);
rdev_dec_pending(rdev, mddev);
- rcu_read_lock();
}
}
- rcu_read_unlock();
+ spin_unlock_irqrestore(&conf->device_lock, flags);
}
static void raid6_unplug_device(request_queue_t *q)
raid6_conf_t *conf = mddev_to_conf(mddev);
int i, ret = 0;
- rcu_read_lock();
- for (i=0; i<mddev->raid_disks && ret == 0; i++) {
+ for (i=0; i<mddev->raid_disks; i++) {
mdk_rdev_t *rdev = conf->disks[i].rdev;
if (rdev && !rdev->faulty) {
struct block_device *bdev = rdev->bdev;
- request_queue_t *r_queue = bdev_get_queue(bdev);
+ request_queue_t *r_queue;
- if (!r_queue->issue_flush_fn)
+ if (!bdev)
+ continue;
+
+ r_queue = bdev_get_queue(bdev);
+ if (!r_queue)
+ continue;
+
+ 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();
+ break;
}
+
+ ret = r_queue->issue_flush_fn(r_queue, bdev->bd_disk, error_sector);
+ if (ret)
+ break;
}
}
- rcu_read_unlock();
return ret;
}
new_sector = raid6_compute_sector(logical_sector,
raid_disks, data_disks, &dd_idx, &pd_idx, conf);
- PRINTK("raid6: make_request, sector %llu logical %llu\n",
+ PRINTK("raid6: make_request, sector %Lu logical %Lu\n",
(unsigned long long)new_sector,
(unsigned long long)logical_sector);
mddev->thread = NULL;
shrink_stripes(conf);
free_pages((unsigned long) conf->stripe_hashtbl, HASH_PAGES_ORDER);
- blk_sync_queue(mddev->queue); /* the unplug fn references 'conf'*/
kfree(conf);
mddev->private = NULL;
return 0;
raid6_conf_t *conf = mddev->private;
struct disk_info *tmp;
+ spin_lock_irq(&conf->device_lock);
for (i = 0; i < conf->raid_disks; i++) {
tmp = conf->disks + i;
if (tmp->rdev
tmp->rdev->in_sync = 1;
}
}
+ spin_unlock_irq(&conf->device_lock);
print_raid6_conf(conf);
return 0;
}
static int raid6_remove_disk(mddev_t *mddev, int number)
{
raid6_conf_t *conf = mddev->private;
- int err = 0;
- mdk_rdev_t *rdev;
+ int err = 1;
struct disk_info *p = conf->disks + number;
print_raid6_conf(conf);
- rdev = p->rdev;
- if (rdev) {
- if (rdev->in_sync ||
- atomic_read(&rdev->nr_pending)) {
+ spin_lock_irq(&conf->device_lock);
+
+ if (p->rdev) {
+ if (p->rdev->in_sync ||
+ atomic_read(&p->rdev->nr_pending)) {
err = -EBUSY;
goto abort;
}
p->rdev = NULL;
- synchronize_kernel();
- if (atomic_read(&rdev->nr_pending)) {
- /* lost the race, try later */
- err = -EBUSY;
- p->rdev = rdev;
- }
+ err = 0;
}
-
+ if (err)
+ MD_BUG();
abort:
-
+ spin_unlock_irq(&conf->device_lock);
print_raid6_conf(conf);
return err;
}
int disk;
struct disk_info *p;
+ spin_lock_irq(&conf->device_lock);
/*
* find the disk ...
*/
for (disk=0; disk < mddev->raid_disks; disk++)
if ((p=conf->disks + disk)->rdev == NULL) {
+ p->rdev = rdev;
rdev->in_sync = 0;
rdev->raid_disk = disk;
found = 1;
- p->rdev = rdev;
break;
}
+ spin_unlock_irq(&conf->device_lock);
print_raid6_conf(conf);
return found;
}