提交 6e451397 编写于 作者: L Linus Torvalds

Merge branch 'for-linus' of git://neil.brown.name/md

* 'for-linus' of git://neil.brown.name/md: (45 commits)
  md: don't insist on valid event count for spare devices.
  md: simplify updating of event count to sometimes avoid updating spares.
  md/raid6: Fix raid-6 read-error correction in degraded state
  md: restore ability of spare drives to spin down.
  md: Fix read balancing in RAID1 and RAID10 on drives > 2TB
  md/linear: standardise all printk messages
  md/raid0: tidy up printk messages.
  md/raid10: tidy up printk messages.
  md/raid1: improve printk messages
  md/raid5: improve consistency of error messages.
  md: remove EXPERIMENTAL designation from RAID10
  md: allow integers to be passed to md/level
  md: notify mdstat waiters of level change
  md/raid4: permit raid0 takeover
  md/raid1: delay reads that could overtake behind-writes.
  md/raid1: fix confusing 'redirect sector' message.
  md: don't unregister the thread in mddev_suspend
  md: factor out init code for an mddev
  md: pass mddev to make_request functions rather than request_queue
  md: call md_stop_writes from md_stop
  ...
...@@ -100,8 +100,8 @@ config MD_RAID1 ...@@ -100,8 +100,8 @@ config MD_RAID1
If unsure, say Y. If unsure, say Y.
config MD_RAID10 config MD_RAID10
tristate "RAID-10 (mirrored striping) mode (EXPERIMENTAL)" tristate "RAID-10 (mirrored striping) mode"
depends on BLK_DEV_MD && EXPERIMENTAL depends on BLK_DEV_MD
---help--- ---help---
RAID-10 provides a combination of striping (RAID-0) and RAID-10 provides a combination of striping (RAID-0) and
mirroring (RAID-1) with easier configuration and more flexible mirroring (RAID-1) with easier configuration and more flexible
......
...@@ -505,7 +505,7 @@ void bitmap_update_sb(struct bitmap *bitmap) ...@@ -505,7 +505,7 @@ void bitmap_update_sb(struct bitmap *bitmap)
return; return;
} }
spin_unlock_irqrestore(&bitmap->lock, flags); spin_unlock_irqrestore(&bitmap->lock, flags);
sb = (bitmap_super_t *)kmap_atomic(bitmap->sb_page, KM_USER0); sb = kmap_atomic(bitmap->sb_page, KM_USER0);
sb->events = cpu_to_le64(bitmap->mddev->events); sb->events = cpu_to_le64(bitmap->mddev->events);
if (bitmap->mddev->events < bitmap->events_cleared) { if (bitmap->mddev->events < bitmap->events_cleared) {
/* rocking back to read-only */ /* rocking back to read-only */
...@@ -526,7 +526,7 @@ void bitmap_print_sb(struct bitmap *bitmap) ...@@ -526,7 +526,7 @@ void bitmap_print_sb(struct bitmap *bitmap)
if (!bitmap || !bitmap->sb_page) if (!bitmap || !bitmap->sb_page)
return; return;
sb = (bitmap_super_t *)kmap_atomic(bitmap->sb_page, KM_USER0); sb = kmap_atomic(bitmap->sb_page, KM_USER0);
printk(KERN_DEBUG "%s: bitmap file superblock:\n", bmname(bitmap)); printk(KERN_DEBUG "%s: bitmap file superblock:\n", bmname(bitmap));
printk(KERN_DEBUG " magic: %08x\n", le32_to_cpu(sb->magic)); printk(KERN_DEBUG " magic: %08x\n", le32_to_cpu(sb->magic));
printk(KERN_DEBUG " version: %d\n", le32_to_cpu(sb->version)); printk(KERN_DEBUG " version: %d\n", le32_to_cpu(sb->version));
...@@ -575,7 +575,7 @@ static int bitmap_read_sb(struct bitmap *bitmap) ...@@ -575,7 +575,7 @@ static int bitmap_read_sb(struct bitmap *bitmap)
return err; return err;
} }
sb = (bitmap_super_t *)kmap_atomic(bitmap->sb_page, KM_USER0); sb = kmap_atomic(bitmap->sb_page, KM_USER0);
chunksize = le32_to_cpu(sb->chunksize); chunksize = le32_to_cpu(sb->chunksize);
daemon_sleep = le32_to_cpu(sb->daemon_sleep) * HZ; daemon_sleep = le32_to_cpu(sb->daemon_sleep) * HZ;
...@@ -661,7 +661,7 @@ static int bitmap_mask_state(struct bitmap *bitmap, enum bitmap_state bits, ...@@ -661,7 +661,7 @@ static int bitmap_mask_state(struct bitmap *bitmap, enum bitmap_state bits,
return 0; return 0;
} }
spin_unlock_irqrestore(&bitmap->lock, flags); spin_unlock_irqrestore(&bitmap->lock, flags);
sb = (bitmap_super_t *)kmap_atomic(bitmap->sb_page, KM_USER0); sb = kmap_atomic(bitmap->sb_page, KM_USER0);
old = le32_to_cpu(sb->state) & bits; old = le32_to_cpu(sb->state) & bits;
switch (op) { switch (op) {
case MASK_SET: sb->state |= cpu_to_le32(bits); case MASK_SET: sb->state |= cpu_to_le32(bits);
...@@ -1292,9 +1292,14 @@ int bitmap_startwrite(struct bitmap *bitmap, sector_t offset, unsigned long sect ...@@ -1292,9 +1292,14 @@ int bitmap_startwrite(struct bitmap *bitmap, sector_t offset, unsigned long sect
if (!bitmap) return 0; if (!bitmap) return 0;
if (behind) { if (behind) {
int bw;
atomic_inc(&bitmap->behind_writes); atomic_inc(&bitmap->behind_writes);
bw = atomic_read(&bitmap->behind_writes);
if (bw > bitmap->behind_writes_used)
bitmap->behind_writes_used = bw;
PRINTK(KERN_DEBUG "inc write-behind count %d/%d\n", PRINTK(KERN_DEBUG "inc write-behind count %d/%d\n",
atomic_read(&bitmap->behind_writes), bitmap->max_write_behind); bw, bitmap->max_write_behind);
} }
while (sectors) { while (sectors) {
...@@ -1351,7 +1356,8 @@ void bitmap_endwrite(struct bitmap *bitmap, sector_t offset, unsigned long secto ...@@ -1351,7 +1356,8 @@ void bitmap_endwrite(struct bitmap *bitmap, sector_t offset, unsigned long secto
{ {
if (!bitmap) return; if (!bitmap) return;
if (behind) { if (behind) {
atomic_dec(&bitmap->behind_writes); if (atomic_dec_and_test(&bitmap->behind_writes))
wake_up(&bitmap->behind_wait);
PRINTK(KERN_DEBUG "dec write-behind count %d/%d\n", PRINTK(KERN_DEBUG "dec write-behind count %d/%d\n",
atomic_read(&bitmap->behind_writes), bitmap->max_write_behind); atomic_read(&bitmap->behind_writes), bitmap->max_write_behind);
} }
...@@ -1675,6 +1681,7 @@ int bitmap_create(mddev_t *mddev) ...@@ -1675,6 +1681,7 @@ int bitmap_create(mddev_t *mddev)
atomic_set(&bitmap->pending_writes, 0); atomic_set(&bitmap->pending_writes, 0);
init_waitqueue_head(&bitmap->write_wait); init_waitqueue_head(&bitmap->write_wait);
init_waitqueue_head(&bitmap->overflow_wait); init_waitqueue_head(&bitmap->overflow_wait);
init_waitqueue_head(&bitmap->behind_wait);
bitmap->mddev = mddev; bitmap->mddev = mddev;
...@@ -2006,6 +2013,27 @@ static ssize_t can_clear_store(mddev_t *mddev, const char *buf, size_t len) ...@@ -2006,6 +2013,27 @@ static ssize_t can_clear_store(mddev_t *mddev, const char *buf, size_t len)
static struct md_sysfs_entry bitmap_can_clear = static struct md_sysfs_entry bitmap_can_clear =
__ATTR(can_clear, S_IRUGO|S_IWUSR, can_clear_show, can_clear_store); __ATTR(can_clear, S_IRUGO|S_IWUSR, can_clear_show, can_clear_store);
static ssize_t
behind_writes_used_show(mddev_t *mddev, char *page)
{
if (mddev->bitmap == NULL)
return sprintf(page, "0\n");
return sprintf(page, "%lu\n",
mddev->bitmap->behind_writes_used);
}
static ssize_t
behind_writes_used_reset(mddev_t *mddev, const char *buf, size_t len)
{
if (mddev->bitmap)
mddev->bitmap->behind_writes_used = 0;
return len;
}
static struct md_sysfs_entry max_backlog_used =
__ATTR(max_backlog_used, S_IRUGO | S_IWUSR,
behind_writes_used_show, behind_writes_used_reset);
static struct attribute *md_bitmap_attrs[] = { static struct attribute *md_bitmap_attrs[] = {
&bitmap_location.attr, &bitmap_location.attr,
&bitmap_timeout.attr, &bitmap_timeout.attr,
...@@ -2013,6 +2041,7 @@ static struct attribute *md_bitmap_attrs[] = { ...@@ -2013,6 +2041,7 @@ static struct attribute *md_bitmap_attrs[] = {
&bitmap_chunksize.attr, &bitmap_chunksize.attr,
&bitmap_metadata.attr, &bitmap_metadata.attr,
&bitmap_can_clear.attr, &bitmap_can_clear.attr,
&max_backlog_used.attr,
NULL NULL
}; };
struct attribute_group md_bitmap_group = { struct attribute_group md_bitmap_group = {
......
...@@ -227,6 +227,7 @@ struct bitmap { ...@@ -227,6 +227,7 @@ struct bitmap {
int allclean; int allclean;
atomic_t behind_writes; atomic_t behind_writes;
unsigned long behind_writes_used; /* highest actual value at runtime */
/* /*
* the bitmap daemon - periodically wakes up and sweeps the bitmap * the bitmap daemon - periodically wakes up and sweeps the bitmap
...@@ -239,6 +240,7 @@ struct bitmap { ...@@ -239,6 +240,7 @@ struct bitmap {
atomic_t pending_writes; /* pending writes to the bitmap file */ atomic_t pending_writes; /* pending writes to the bitmap file */
wait_queue_head_t write_wait; wait_queue_head_t write_wait;
wait_queue_head_t overflow_wait; wait_queue_head_t overflow_wait;
wait_queue_head_t behind_wait;
struct sysfs_dirent *sysfs_can_clear; struct sysfs_dirent *sysfs_can_clear;
}; };
......
...@@ -169,10 +169,9 @@ static void add_sector(conf_t *conf, sector_t start, int mode) ...@@ -169,10 +169,9 @@ static void add_sector(conf_t *conf, sector_t start, int mode)
conf->nfaults = n+1; conf->nfaults = n+1;
} }
static int make_request(struct request_queue *q, struct bio *bio) static int make_request(mddev_t *mddev, struct bio *bio)
{ {
mddev_t *mddev = q->queuedata; conf_t *conf = mddev->private;
conf_t *conf = (conf_t*)mddev->private;
int failit = 0; int failit = 0;
if (bio_data_dir(bio) == WRITE) { if (bio_data_dir(bio) == WRITE) {
...@@ -225,7 +224,7 @@ static int make_request(struct request_queue *q, struct bio *bio) ...@@ -225,7 +224,7 @@ static int make_request(struct request_queue *q, struct bio *bio)
static void status(struct seq_file *seq, mddev_t *mddev) static void status(struct seq_file *seq, mddev_t *mddev)
{ {
conf_t *conf = (conf_t*)mddev->private; conf_t *conf = mddev->private;
int n; int n;
if ((n=atomic_read(&conf->counters[WriteTransient])) != 0) if ((n=atomic_read(&conf->counters[WriteTransient])) != 0)
...@@ -328,7 +327,7 @@ static int run(mddev_t *mddev) ...@@ -328,7 +327,7 @@ static int run(mddev_t *mddev)
static int stop(mddev_t *mddev) static int stop(mddev_t *mddev)
{ {
conf_t *conf = (conf_t *)mddev->private; conf_t *conf = mddev->private;
kfree(conf); kfree(conf);
mddev->private = NULL; mddev->private = NULL;
......
...@@ -159,7 +159,8 @@ static linear_conf_t *linear_conf(mddev_t *mddev, int raid_disks) ...@@ -159,7 +159,8 @@ static linear_conf_t *linear_conf(mddev_t *mddev, int raid_disks)
sector_t sectors; sector_t sectors;
if (j < 0 || j >= raid_disks || disk->rdev) { if (j < 0 || j >= raid_disks || disk->rdev) {
printk("linear: disk numbering problem. Aborting!\n"); printk(KERN_ERR "md/linear:%s: disk numbering problem. Aborting!\n",
mdname(mddev));
goto out; goto out;
} }
...@@ -187,7 +188,8 @@ static linear_conf_t *linear_conf(mddev_t *mddev, int raid_disks) ...@@ -187,7 +188,8 @@ static linear_conf_t *linear_conf(mddev_t *mddev, int raid_disks)
} }
if (cnt != raid_disks) { if (cnt != raid_disks) {
printk("linear: not enough drives present. Aborting!\n"); printk(KERN_ERR "md/linear:%s: not enough drives present. Aborting!\n",
mdname(mddev));
goto out; goto out;
} }
...@@ -282,29 +284,21 @@ static int linear_stop (mddev_t *mddev) ...@@ -282,29 +284,21 @@ static int linear_stop (mddev_t *mddev)
rcu_barrier(); rcu_barrier();
blk_sync_queue(mddev->queue); /* the unplug fn references 'conf'*/ blk_sync_queue(mddev->queue); /* the unplug fn references 'conf'*/
kfree(conf); kfree(conf);
mddev->private = NULL;
return 0; return 0;
} }
static int linear_make_request (struct request_queue *q, struct bio *bio) static int linear_make_request (mddev_t *mddev, struct bio *bio)
{ {
const int rw = bio_data_dir(bio);
mddev_t *mddev = q->queuedata;
dev_info_t *tmp_dev; dev_info_t *tmp_dev;
sector_t start_sector; sector_t start_sector;
int cpu;
if (unlikely(bio_rw_flagged(bio, BIO_RW_BARRIER))) { if (unlikely(bio_rw_flagged(bio, BIO_RW_BARRIER))) {
md_barrier_request(mddev, bio); md_barrier_request(mddev, bio);
return 0; return 0;
} }
cpu = part_stat_lock();
part_stat_inc(cpu, &mddev->gendisk->part0, ios[rw]);
part_stat_add(cpu, &mddev->gendisk->part0, sectors[rw],
bio_sectors(bio));
part_stat_unlock();
rcu_read_lock(); rcu_read_lock();
tmp_dev = which_dev(mddev, bio->bi_sector); tmp_dev = which_dev(mddev, bio->bi_sector);
start_sector = tmp_dev->end_sector - tmp_dev->rdev->sectors; start_sector = tmp_dev->end_sector - tmp_dev->rdev->sectors;
...@@ -314,12 +308,14 @@ static int linear_make_request (struct request_queue *q, struct bio *bio) ...@@ -314,12 +308,14 @@ static int linear_make_request (struct request_queue *q, struct bio *bio)
|| (bio->bi_sector < start_sector))) { || (bio->bi_sector < start_sector))) {
char b[BDEVNAME_SIZE]; char b[BDEVNAME_SIZE];
printk("linear_make_request: Sector %llu out of bounds on " printk(KERN_ERR
"dev %s: %llu sectors, offset %llu\n", "md/linear:%s: make_request: Sector %llu out of bounds on "
(unsigned long long)bio->bi_sector, "dev %s: %llu sectors, offset %llu\n",
bdevname(tmp_dev->rdev->bdev, b), mdname(mddev),
(unsigned long long)tmp_dev->rdev->sectors, (unsigned long long)bio->bi_sector,
(unsigned long long)start_sector); bdevname(tmp_dev->rdev->bdev, b),
(unsigned long long)tmp_dev->rdev->sectors,
(unsigned long long)start_sector);
rcu_read_unlock(); rcu_read_unlock();
bio_io_error(bio); bio_io_error(bio);
return 0; return 0;
...@@ -336,9 +332,9 @@ static int linear_make_request (struct request_queue *q, struct bio *bio) ...@@ -336,9 +332,9 @@ static int linear_make_request (struct request_queue *q, struct bio *bio)
bp = bio_split(bio, end_sector - bio->bi_sector); bp = bio_split(bio, end_sector - bio->bi_sector);
if (linear_make_request(q, &bp->bio1)) if (linear_make_request(mddev, &bp->bio1))
generic_make_request(&bp->bio1); generic_make_request(&bp->bio1);
if (linear_make_request(q, &bp->bio2)) if (linear_make_request(mddev, &bp->bio2))
generic_make_request(&bp->bio2); generic_make_request(&bp->bio2);
bio_pair_release(bp); bio_pair_release(bp);
return 0; return 0;
......
此差异已折叠。
...@@ -74,9 +74,6 @@ struct mdk_rdev_s ...@@ -74,9 +74,6 @@ struct mdk_rdev_s
#define Blocked 8 /* An error occured on an externally #define Blocked 8 /* An error occured on an externally
* managed array, don't allow writes * managed array, don't allow writes
* until it is cleared */ * until it is cleared */
#define StateChanged 9 /* Faulty or Blocked has changed during
* interrupt, so it needs to be
* notified by the thread */
wait_queue_head_t blocked_wait; wait_queue_head_t blocked_wait;
int desc_nr; /* descriptor index in the superblock */ int desc_nr; /* descriptor index in the superblock */
...@@ -153,6 +150,12 @@ struct mddev_s ...@@ -153,6 +150,12 @@ struct mddev_s
int external_size; /* size managed int external_size; /* size managed
* externally */ * externally */
__u64 events; __u64 events;
/* If the last 'event' was simply a clean->dirty transition, and
* we didn't write it to the spares, then it is safe and simple
* to just decrement the event count on a dirty->clean transition.
* So we record that possibility here.
*/
int can_decrease_events;
char uuid[16]; char uuid[16];
...@@ -240,7 +243,6 @@ struct mddev_s ...@@ -240,7 +243,6 @@ struct mddev_s
atomic_t active; /* general refcount */ atomic_t active; /* general refcount */
atomic_t openers; /* number of active opens */ atomic_t openers; /* number of active opens */
int changed; /* true if we might need to reread partition info */
int degraded; /* whether md should consider int degraded; /* whether md should consider
* adding a spare * adding a spare
*/ */
...@@ -279,9 +281,6 @@ struct mddev_s ...@@ -279,9 +281,6 @@ struct mddev_s
atomic_t writes_pending; atomic_t writes_pending;
struct request_queue *queue; /* for plugging ... */ struct request_queue *queue; /* for plugging ... */
atomic_t write_behind; /* outstanding async IO */
unsigned int max_write_behind; /* 0 = sync */
struct bitmap *bitmap; /* the bitmap for the device */ struct bitmap *bitmap; /* the bitmap for the device */
struct { struct {
struct file *file; /* the bitmap file */ struct file *file; /* the bitmap file */
...@@ -305,6 +304,7 @@ struct mddev_s ...@@ -305,6 +304,7 @@ struct mddev_s
atomic_t max_corr_read_errors; /* max read retries */ atomic_t max_corr_read_errors; /* max read retries */
struct list_head all_mddevs; struct list_head all_mddevs;
struct attribute_group *to_remove;
/* Generic barrier handling. /* Generic barrier handling.
* If there is a pending barrier request, all other * If there is a pending barrier request, all other
* writes are blocked while the devices are flushed. * writes are blocked while the devices are flushed.
...@@ -336,7 +336,7 @@ struct mdk_personality ...@@ -336,7 +336,7 @@ struct mdk_personality
int level; int level;
struct list_head list; struct list_head list;
struct module *owner; struct module *owner;
int (*make_request)(struct request_queue *q, struct bio *bio); int (*make_request)(mddev_t *mddev, struct bio *bio);
int (*run)(mddev_t *mddev); int (*run)(mddev_t *mddev);
int (*stop)(mddev_t *mddev); int (*stop)(mddev_t *mddev);
void (*status)(struct seq_file *seq, mddev_t *mddev); void (*status)(struct seq_file *seq, mddev_t *mddev);
......
...@@ -85,7 +85,7 @@ static void multipath_end_bh_io (struct multipath_bh *mp_bh, int err) ...@@ -85,7 +85,7 @@ static void multipath_end_bh_io (struct multipath_bh *mp_bh, int err)
static void multipath_end_request(struct bio *bio, int error) static void multipath_end_request(struct bio *bio, int error)
{ {
int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags); int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags);
struct multipath_bh * mp_bh = (struct multipath_bh *)(bio->bi_private); struct multipath_bh *mp_bh = bio->bi_private;
multipath_conf_t *conf = mp_bh->mddev->private; multipath_conf_t *conf = mp_bh->mddev->private;
mdk_rdev_t *rdev = conf->multipaths[mp_bh->path].rdev; mdk_rdev_t *rdev = conf->multipaths[mp_bh->path].rdev;
...@@ -136,14 +136,11 @@ static void multipath_unplug(struct request_queue *q) ...@@ -136,14 +136,11 @@ static void multipath_unplug(struct request_queue *q)
} }
static int multipath_make_request (struct request_queue *q, struct bio * bio) static int multipath_make_request(mddev_t *mddev, struct bio * bio)
{ {
mddev_t *mddev = q->queuedata;
multipath_conf_t *conf = mddev->private; multipath_conf_t *conf = mddev->private;
struct multipath_bh * mp_bh; struct multipath_bh * mp_bh;
struct multipath_info *multipath; struct multipath_info *multipath;
const int rw = bio_data_dir(bio);
int cpu;
if (unlikely(bio_rw_flagged(bio, BIO_RW_BARRIER))) { if (unlikely(bio_rw_flagged(bio, BIO_RW_BARRIER))) {
md_barrier_request(mddev, bio); md_barrier_request(mddev, bio);
...@@ -155,12 +152,6 @@ static int multipath_make_request (struct request_queue *q, struct bio * bio) ...@@ -155,12 +152,6 @@ static int multipath_make_request (struct request_queue *q, struct bio * bio)
mp_bh->master_bio = bio; mp_bh->master_bio = bio;
mp_bh->mddev = mddev; mp_bh->mddev = mddev;
cpu = part_stat_lock();
part_stat_inc(cpu, &mddev->gendisk->part0, ios[rw]);
part_stat_add(cpu, &mddev->gendisk->part0, sectors[rw],
bio_sectors(bio));
part_stat_unlock();
mp_bh->path = multipath_map(conf); mp_bh->path = multipath_map(conf);
if (mp_bh->path < 0) { if (mp_bh->path < 0) {
bio_endio(bio, -EIO); bio_endio(bio, -EIO);
......
...@@ -23,15 +23,17 @@ ...@@ -23,15 +23,17 @@
#include <linux/slab.h> #include <linux/slab.h>
#include "md.h" #include "md.h"
#include "raid0.h" #include "raid0.h"
#include "raid5.h"
static void raid0_unplug(struct request_queue *q) static void raid0_unplug(struct request_queue *q)
{ {
mddev_t *mddev = q->queuedata; mddev_t *mddev = q->queuedata;
raid0_conf_t *conf = mddev->private; raid0_conf_t *conf = mddev->private;
mdk_rdev_t **devlist = conf->devlist; mdk_rdev_t **devlist = conf->devlist;
int raid_disks = conf->strip_zone[0].nb_dev;
int i; int i;
for (i=0; i<mddev->raid_disks; i++) { for (i=0; i < raid_disks; i++) {
struct request_queue *r_queue = bdev_get_queue(devlist[i]->bdev); struct request_queue *r_queue = bdev_get_queue(devlist[i]->bdev);
blk_unplug(r_queue); blk_unplug(r_queue);
...@@ -43,12 +45,13 @@ static int raid0_congested(void *data, int bits) ...@@ -43,12 +45,13 @@ static int raid0_congested(void *data, int bits)
mddev_t *mddev = data; mddev_t *mddev = data;
raid0_conf_t *conf = mddev->private; raid0_conf_t *conf = mddev->private;
mdk_rdev_t **devlist = conf->devlist; mdk_rdev_t **devlist = conf->devlist;
int raid_disks = conf->strip_zone[0].nb_dev;
int i, ret = 0; int i, ret = 0;
if (mddev_congested(mddev, bits)) if (mddev_congested(mddev, bits))
return 1; return 1;
for (i = 0; i < mddev->raid_disks && !ret ; i++) { for (i = 0; i < raid_disks && !ret ; i++) {
struct request_queue *q = bdev_get_queue(devlist[i]->bdev); struct request_queue *q = bdev_get_queue(devlist[i]->bdev);
ret |= bdi_congested(&q->backing_dev_info, bits); ret |= bdi_congested(&q->backing_dev_info, bits);
...@@ -66,16 +69,17 @@ static void dump_zones(mddev_t *mddev) ...@@ -66,16 +69,17 @@ static void dump_zones(mddev_t *mddev)
sector_t zone_start = 0; sector_t zone_start = 0;
char b[BDEVNAME_SIZE]; char b[BDEVNAME_SIZE];
raid0_conf_t *conf = mddev->private; raid0_conf_t *conf = mddev->private;
int raid_disks = conf->strip_zone[0].nb_dev;
printk(KERN_INFO "******* %s configuration *********\n", printk(KERN_INFO "******* %s configuration *********\n",
mdname(mddev)); mdname(mddev));
h = 0; h = 0;
for (j = 0; j < conf->nr_strip_zones; j++) { for (j = 0; j < conf->nr_strip_zones; j++) {
printk(KERN_INFO "zone%d=[", j); printk(KERN_INFO "zone%d=[", j);
for (k = 0; k < conf->strip_zone[j].nb_dev; k++) for (k = 0; k < conf->strip_zone[j].nb_dev; k++)
printk("%s/", printk(KERN_CONT "%s/",
bdevname(conf->devlist[j*mddev->raid_disks bdevname(conf->devlist[j*raid_disks
+ k]->bdev, b)); + k]->bdev, b));
printk("]\n"); printk(KERN_CONT "]\n");
zone_size = conf->strip_zone[j].zone_end - zone_start; zone_size = conf->strip_zone[j].zone_end - zone_start;
printk(KERN_INFO " zone offset=%llukb " printk(KERN_INFO " zone offset=%llukb "
...@@ -88,7 +92,7 @@ static void dump_zones(mddev_t *mddev) ...@@ -88,7 +92,7 @@ static void dump_zones(mddev_t *mddev)
printk(KERN_INFO "**********************************\n\n"); printk(KERN_INFO "**********************************\n\n");
} }
static int create_strip_zones(mddev_t *mddev) static int create_strip_zones(mddev_t *mddev, raid0_conf_t **private_conf)
{ {
int i, c, err; int i, c, err;
sector_t curr_zone_end, sectors; sector_t curr_zone_end, sectors;
...@@ -101,8 +105,9 @@ static int create_strip_zones(mddev_t *mddev) ...@@ -101,8 +105,9 @@ static int create_strip_zones(mddev_t *mddev)
if (!conf) if (!conf)
return -ENOMEM; return -ENOMEM;
list_for_each_entry(rdev1, &mddev->disks, same_set) { list_for_each_entry(rdev1, &mddev->disks, same_set) {
printk(KERN_INFO "raid0: looking at %s\n", printk(KERN_INFO "md/raid0:%s: looking at %s\n",
bdevname(rdev1->bdev,b)); mdname(mddev),
bdevname(rdev1->bdev, b));
c = 0; c = 0;
/* round size to chunk_size */ /* round size to chunk_size */
...@@ -111,14 +116,16 @@ static int create_strip_zones(mddev_t *mddev) ...@@ -111,14 +116,16 @@ static int create_strip_zones(mddev_t *mddev)
rdev1->sectors = sectors * mddev->chunk_sectors; rdev1->sectors = sectors * mddev->chunk_sectors;
list_for_each_entry(rdev2, &mddev->disks, same_set) { list_for_each_entry(rdev2, &mddev->disks, same_set) {
printk(KERN_INFO "raid0: comparing %s(%llu)", printk(KERN_INFO "md/raid0:%s: comparing %s(%llu)",
mdname(mddev),
bdevname(rdev1->bdev,b), bdevname(rdev1->bdev,b),
(unsigned long long)rdev1->sectors); (unsigned long long)rdev1->sectors);
printk(KERN_INFO " with %s(%llu)\n", printk(KERN_CONT " with %s(%llu)\n",
bdevname(rdev2->bdev,b), bdevname(rdev2->bdev,b),
(unsigned long long)rdev2->sectors); (unsigned long long)rdev2->sectors);
if (rdev2 == rdev1) { if (rdev2 == rdev1) {
printk(KERN_INFO "raid0: END\n"); printk(KERN_INFO "md/raid0:%s: END\n",
mdname(mddev));
break; break;
} }
if (rdev2->sectors == rdev1->sectors) { if (rdev2->sectors == rdev1->sectors) {
...@@ -126,20 +133,24 @@ static int create_strip_zones(mddev_t *mddev) ...@@ -126,20 +133,24 @@ static int create_strip_zones(mddev_t *mddev)
* Not unique, don't count it as a new * Not unique, don't count it as a new
* group * group
*/ */
printk(KERN_INFO "raid0: EQUAL\n"); printk(KERN_INFO "md/raid0:%s: EQUAL\n",
mdname(mddev));
c = 1; c = 1;
break; break;
} }
printk(KERN_INFO "raid0: NOT EQUAL\n"); printk(KERN_INFO "md/raid0:%s: NOT EQUAL\n",
mdname(mddev));
} }
if (!c) { if (!c) {
printk(KERN_INFO "raid0: ==> UNIQUE\n"); printk(KERN_INFO "md/raid0:%s: ==> UNIQUE\n",
mdname(mddev));
conf->nr_strip_zones++; conf->nr_strip_zones++;
printk(KERN_INFO "raid0: %d zones\n", printk(KERN_INFO "md/raid0:%s: %d zones\n",
conf->nr_strip_zones); mdname(mddev), conf->nr_strip_zones);
} }
} }
printk(KERN_INFO "raid0: FINAL %d zones\n", conf->nr_strip_zones); printk(KERN_INFO "md/raid0:%s: FINAL %d zones\n",
mdname(mddev), conf->nr_strip_zones);
err = -ENOMEM; err = -ENOMEM;
conf->strip_zone = kzalloc(sizeof(struct strip_zone)* conf->strip_zone = kzalloc(sizeof(struct strip_zone)*
conf->nr_strip_zones, GFP_KERNEL); conf->nr_strip_zones, GFP_KERNEL);
...@@ -162,14 +173,18 @@ static int create_strip_zones(mddev_t *mddev) ...@@ -162,14 +173,18 @@ static int create_strip_zones(mddev_t *mddev)
list_for_each_entry(rdev1, &mddev->disks, same_set) { list_for_each_entry(rdev1, &mddev->disks, same_set) {
int j = rdev1->raid_disk; int j = rdev1->raid_disk;
if (mddev->level == 10)
/* taking over a raid10-n2 array */
j /= 2;
if (j < 0 || j >= mddev->raid_disks) { if (j < 0 || j >= mddev->raid_disks) {
printk(KERN_ERR "raid0: bad disk number %d - " printk(KERN_ERR "md/raid0:%s: bad disk number %d - "
"aborting!\n", j); "aborting!\n", mdname(mddev), j);
goto abort; goto abort;
} }
if (dev[j]) { if (dev[j]) {
printk(KERN_ERR "raid0: multiple devices for %d - " printk(KERN_ERR "md/raid0:%s: multiple devices for %d - "
"aborting!\n", j); "aborting!\n", mdname(mddev), j);
goto abort; goto abort;
} }
dev[j] = rdev1; dev[j] = rdev1;
...@@ -191,8 +206,8 @@ static int create_strip_zones(mddev_t *mddev) ...@@ -191,8 +206,8 @@ static int create_strip_zones(mddev_t *mddev)
cnt++; cnt++;
} }
if (cnt != mddev->raid_disks) { if (cnt != mddev->raid_disks) {
printk(KERN_ERR "raid0: too few disks (%d of %d) - " printk(KERN_ERR "md/raid0:%s: too few disks (%d of %d) - "
"aborting!\n", cnt, mddev->raid_disks); "aborting!\n", mdname(mddev), cnt, mddev->raid_disks);
goto abort; goto abort;
} }
zone->nb_dev = cnt; zone->nb_dev = cnt;
...@@ -208,39 +223,44 @@ static int create_strip_zones(mddev_t *mddev) ...@@ -208,39 +223,44 @@ static int create_strip_zones(mddev_t *mddev)
zone = conf->strip_zone + i; zone = conf->strip_zone + i;
dev = conf->devlist + i * mddev->raid_disks; dev = conf->devlist + i * mddev->raid_disks;
printk(KERN_INFO "raid0: zone %d\n", i); printk(KERN_INFO "md/raid0:%s: zone %d\n",
mdname(mddev), i);
zone->dev_start = smallest->sectors; zone->dev_start = smallest->sectors;
smallest = NULL; smallest = NULL;
c = 0; c = 0;
for (j=0; j<cnt; j++) { for (j=0; j<cnt; j++) {
rdev = conf->devlist[j]; rdev = conf->devlist[j];
printk(KERN_INFO "raid0: checking %s ...", printk(KERN_INFO "md/raid0:%s: checking %s ...",
bdevname(rdev->bdev, b)); mdname(mddev),
bdevname(rdev->bdev, b));
if (rdev->sectors <= zone->dev_start) { if (rdev->sectors <= zone->dev_start) {
printk(KERN_INFO " nope.\n"); printk(KERN_CONT " nope.\n");
continue; continue;
} }
printk(KERN_INFO " contained as device %d\n", c); printk(KERN_CONT " contained as device %d\n", c);
dev[c] = rdev; dev[c] = rdev;
c++; c++;
if (!smallest || rdev->sectors < smallest->sectors) { if (!smallest || rdev->sectors < smallest->sectors) {
smallest = rdev; smallest = rdev;
printk(KERN_INFO " (%llu) is smallest!.\n", printk(KERN_INFO "md/raid0:%s: (%llu) is smallest!.\n",
(unsigned long long)rdev->sectors); mdname(mddev),
(unsigned long long)rdev->sectors);
} }
} }
zone->nb_dev = c; zone->nb_dev = c;
sectors = (smallest->sectors - zone->dev_start) * c; sectors = (smallest->sectors - zone->dev_start) * c;
printk(KERN_INFO "raid0: zone->nb_dev: %d, sectors: %llu\n", printk(KERN_INFO "md/raid0:%s: zone->nb_dev: %d, sectors: %llu\n",
zone->nb_dev, (unsigned long long)sectors); mdname(mddev),
zone->nb_dev, (unsigned long long)sectors);
curr_zone_end += sectors; curr_zone_end += sectors;
zone->zone_end = curr_zone_end; zone->zone_end = curr_zone_end;
printk(KERN_INFO "raid0: current zone start: %llu\n", printk(KERN_INFO "md/raid0:%s: current zone start: %llu\n",
(unsigned long long)smallest->sectors); mdname(mddev),
(unsigned long long)smallest->sectors);
} }
mddev->queue->unplug_fn = raid0_unplug; mddev->queue->unplug_fn = raid0_unplug;
mddev->queue->backing_dev_info.congested_fn = raid0_congested; mddev->queue->backing_dev_info.congested_fn = raid0_congested;
...@@ -251,7 +271,7 @@ static int create_strip_zones(mddev_t *mddev) ...@@ -251,7 +271,7 @@ static int create_strip_zones(mddev_t *mddev)
* chunk size is a multiple of that sector size * chunk size is a multiple of that sector size
*/ */
if ((mddev->chunk_sectors << 9) % queue_logical_block_size(mddev->queue)) { if ((mddev->chunk_sectors << 9) % queue_logical_block_size(mddev->queue)) {
printk(KERN_ERR "%s chunk_size of %d not valid\n", printk(KERN_ERR "md/raid0:%s: chunk_size of %d not valid\n",
mdname(mddev), mdname(mddev),
mddev->chunk_sectors << 9); mddev->chunk_sectors << 9);
goto abort; goto abort;
...@@ -261,14 +281,15 @@ static int create_strip_zones(mddev_t *mddev) ...@@ -261,14 +281,15 @@ static int create_strip_zones(mddev_t *mddev)
blk_queue_io_opt(mddev->queue, blk_queue_io_opt(mddev->queue,
(mddev->chunk_sectors << 9) * mddev->raid_disks); (mddev->chunk_sectors << 9) * mddev->raid_disks);
printk(KERN_INFO "raid0: done.\n"); printk(KERN_INFO "md/raid0:%s: done.\n", mdname(mddev));
mddev->private = conf; *private_conf = conf;
return 0; return 0;
abort: abort:
kfree(conf->strip_zone); kfree(conf->strip_zone);
kfree(conf->devlist); kfree(conf->devlist);
kfree(conf); kfree(conf);
mddev->private = NULL; *private_conf = NULL;
return err; return err;
} }
...@@ -319,10 +340,12 @@ static sector_t raid0_size(mddev_t *mddev, sector_t sectors, int raid_disks) ...@@ -319,10 +340,12 @@ static sector_t raid0_size(mddev_t *mddev, sector_t sectors, int raid_disks)
static int raid0_run(mddev_t *mddev) static int raid0_run(mddev_t *mddev)
{ {
raid0_conf_t *conf;
int ret; int ret;
if (mddev->chunk_sectors == 0) { if (mddev->chunk_sectors == 0) {
printk(KERN_ERR "md/raid0: chunk size must be set.\n"); printk(KERN_ERR "md/raid0:%s: chunk size must be set.\n",
mdname(mddev));
return -EINVAL; return -EINVAL;
} }
if (md_check_no_bitmap(mddev)) if (md_check_no_bitmap(mddev))
...@@ -330,15 +353,27 @@ static int raid0_run(mddev_t *mddev) ...@@ -330,15 +353,27 @@ static int raid0_run(mddev_t *mddev)
blk_queue_max_hw_sectors(mddev->queue, mddev->chunk_sectors); blk_queue_max_hw_sectors(mddev->queue, mddev->chunk_sectors);
mddev->queue->queue_lock = &mddev->queue->__queue_lock; mddev->queue->queue_lock = &mddev->queue->__queue_lock;
ret = create_strip_zones(mddev); /* if private is not null, we are here after takeover */
if (ret < 0) if (mddev->private == NULL) {
return ret; ret = create_strip_zones(mddev, &conf);
if (ret < 0)
return ret;
mddev->private = conf;
}
conf = mddev->private;
if (conf->scale_raid_disks) {
int i;
for (i=0; i < conf->strip_zone[0].nb_dev; i++)
conf->devlist[i]->raid_disk /= conf->scale_raid_disks;
/* FIXME update sysfs rd links */
}
/* calculate array device size */ /* calculate array device size */
md_set_array_sectors(mddev, raid0_size(mddev, 0, 0)); md_set_array_sectors(mddev, raid0_size(mddev, 0, 0));
printk(KERN_INFO "raid0 : md_size is %llu sectors.\n", printk(KERN_INFO "md/raid0:%s: md_size is %llu sectors.\n",
(unsigned long long)mddev->array_sectors); mdname(mddev),
(unsigned long long)mddev->array_sectors);
/* calculate the max read-ahead size. /* calculate the max read-ahead size.
* For read-ahead of large files to be effective, we need to * For read-ahead of large files to be effective, we need to
* readahead at least twice a whole stripe. i.e. number of devices * readahead at least twice a whole stripe. i.e. number of devices
...@@ -402,6 +437,7 @@ static mdk_rdev_t *map_sector(mddev_t *mddev, struct strip_zone *zone, ...@@ -402,6 +437,7 @@ static mdk_rdev_t *map_sector(mddev_t *mddev, struct strip_zone *zone,
unsigned int sect_in_chunk; unsigned int sect_in_chunk;
sector_t chunk; sector_t chunk;
raid0_conf_t *conf = mddev->private; raid0_conf_t *conf = mddev->private;
int raid_disks = conf->strip_zone[0].nb_dev;
unsigned int chunk_sects = mddev->chunk_sectors; unsigned int chunk_sects = mddev->chunk_sectors;
if (is_power_of_2(chunk_sects)) { if (is_power_of_2(chunk_sects)) {
...@@ -424,7 +460,7 @@ static mdk_rdev_t *map_sector(mddev_t *mddev, struct strip_zone *zone, ...@@ -424,7 +460,7 @@ static mdk_rdev_t *map_sector(mddev_t *mddev, struct strip_zone *zone,
* + the position in the chunk * + the position in the chunk
*/ */
*sector_offset = (chunk * chunk_sects) + sect_in_chunk; *sector_offset = (chunk * chunk_sects) + sect_in_chunk;
return conf->devlist[(zone - conf->strip_zone)*mddev->raid_disks return conf->devlist[(zone - conf->strip_zone)*raid_disks
+ sector_div(sector, zone->nb_dev)]; + sector_div(sector, zone->nb_dev)];
} }
...@@ -444,27 +480,18 @@ static inline int is_io_in_chunk_boundary(mddev_t *mddev, ...@@ -444,27 +480,18 @@ static inline int is_io_in_chunk_boundary(mddev_t *mddev,
} }
} }
static int raid0_make_request(struct request_queue *q, struct bio *bio) static int raid0_make_request(mddev_t *mddev, struct bio *bio)
{ {
mddev_t *mddev = q->queuedata;
unsigned int chunk_sects; unsigned int chunk_sects;
sector_t sector_offset; sector_t sector_offset;
struct strip_zone *zone; struct strip_zone *zone;
mdk_rdev_t *tmp_dev; mdk_rdev_t *tmp_dev;
const int rw = bio_data_dir(bio);
int cpu;
if (unlikely(bio_rw_flagged(bio, BIO_RW_BARRIER))) { if (unlikely(bio_rw_flagged(bio, BIO_RW_BARRIER))) {
md_barrier_request(mddev, bio); md_barrier_request(mddev, bio);
return 0; return 0;
} }
cpu = part_stat_lock();
part_stat_inc(cpu, &mddev->gendisk->part0, ios[rw]);
part_stat_add(cpu, &mddev->gendisk->part0, sectors[rw],
bio_sectors(bio));
part_stat_unlock();
chunk_sects = mddev->chunk_sectors; chunk_sects = mddev->chunk_sectors;
if (unlikely(!is_io_in_chunk_boundary(mddev, chunk_sects, bio))) { if (unlikely(!is_io_in_chunk_boundary(mddev, chunk_sects, bio))) {
sector_t sector = bio->bi_sector; sector_t sector = bio->bi_sector;
...@@ -482,9 +509,9 @@ static int raid0_make_request(struct request_queue *q, struct bio *bio) ...@@ -482,9 +509,9 @@ static int raid0_make_request(struct request_queue *q, struct bio *bio)
else else
bp = bio_split(bio, chunk_sects - bp = bio_split(bio, chunk_sects -
sector_div(sector, chunk_sects)); sector_div(sector, chunk_sects));
if (raid0_make_request(q, &bp->bio1)) if (raid0_make_request(mddev, &bp->bio1))
generic_make_request(&bp->bio1); generic_make_request(&bp->bio1);
if (raid0_make_request(q, &bp->bio2)) if (raid0_make_request(mddev, &bp->bio2))
generic_make_request(&bp->bio2); generic_make_request(&bp->bio2);
bio_pair_release(bp); bio_pair_release(bp);
...@@ -504,9 +531,10 @@ static int raid0_make_request(struct request_queue *q, struct bio *bio) ...@@ -504,9 +531,10 @@ static int raid0_make_request(struct request_queue *q, struct bio *bio)
return 1; return 1;
bad_map: bad_map:
printk("raid0_make_request bug: can't convert block across chunks" printk("md/raid0:%s: make_request bug: can't convert block across chunks"
" or bigger than %dk %llu %d\n", chunk_sects / 2, " or bigger than %dk %llu %d\n",
(unsigned long long)bio->bi_sector, bio->bi_size >> 10); mdname(mddev), chunk_sects / 2,
(unsigned long long)bio->bi_sector, bio->bi_size >> 10);
bio_io_error(bio); bio_io_error(bio);
return 0; return 0;
...@@ -519,6 +547,7 @@ static void raid0_status(struct seq_file *seq, mddev_t *mddev) ...@@ -519,6 +547,7 @@ static void raid0_status(struct seq_file *seq, mddev_t *mddev)
int j, k, h; int j, k, h;
char b[BDEVNAME_SIZE]; char b[BDEVNAME_SIZE];
raid0_conf_t *conf = mddev->private; raid0_conf_t *conf = mddev->private;
int raid_disks = conf->strip_zone[0].nb_dev;
sector_t zone_size; sector_t zone_size;
sector_t zone_start = 0; sector_t zone_start = 0;
...@@ -529,7 +558,7 @@ static void raid0_status(struct seq_file *seq, mddev_t *mddev) ...@@ -529,7 +558,7 @@ static void raid0_status(struct seq_file *seq, mddev_t *mddev)
seq_printf(seq, "=["); seq_printf(seq, "=[");
for (k = 0; k < conf->strip_zone[j].nb_dev; k++) for (k = 0; k < conf->strip_zone[j].nb_dev; k++)
seq_printf(seq, "%s/", bdevname( seq_printf(seq, "%s/", bdevname(
conf->devlist[j*mddev->raid_disks + k] conf->devlist[j*raid_disks + k]
->bdev, b)); ->bdev, b));
zone_size = conf->strip_zone[j].zone_end - zone_start; zone_size = conf->strip_zone[j].zone_end - zone_start;
...@@ -544,6 +573,104 @@ static void raid0_status(struct seq_file *seq, mddev_t *mddev) ...@@ -544,6 +573,104 @@ static void raid0_status(struct seq_file *seq, mddev_t *mddev)
return; return;
} }
static void *raid0_takeover_raid5(mddev_t *mddev)
{
mdk_rdev_t *rdev;
raid0_conf_t *priv_conf;
if (mddev->degraded != 1) {
printk(KERN_ERR "md/raid0:%s: raid5 must be degraded! Degraded disks: %d\n",
mdname(mddev),
mddev->degraded);
return ERR_PTR(-EINVAL);
}
list_for_each_entry(rdev, &mddev->disks, same_set) {
/* check slot number for a disk */
if (rdev->raid_disk == mddev->raid_disks-1) {
printk(KERN_ERR "md/raid0:%s: raid5 must have missing parity disk!\n",
mdname(mddev));
return ERR_PTR(-EINVAL);
}
}
/* Set new parameters */
mddev->new_level = 0;
mddev->new_chunk_sectors = mddev->chunk_sectors;
mddev->raid_disks--;
mddev->delta_disks = -1;
/* make sure it will be not marked as dirty */
mddev->recovery_cp = MaxSector;
create_strip_zones(mddev, &priv_conf);
return priv_conf;
}
static void *raid0_takeover_raid10(mddev_t *mddev)
{
raid0_conf_t *priv_conf;
/* Check layout:
* - far_copies must be 1
* - near_copies must be 2
* - disks number must be even
* - all mirrors must be already degraded
*/
if (mddev->layout != ((1 << 8) + 2)) {
printk(KERN_ERR "md/raid0:%s:: Raid0 cannot takover layout: 0x%x\n",
mdname(mddev),
mddev->layout);
return ERR_PTR(-EINVAL);
}
if (mddev->raid_disks & 1) {
printk(KERN_ERR "md/raid0:%s: Raid0 cannot takover Raid10 with odd disk number.\n",
mdname(mddev));
return ERR_PTR(-EINVAL);
}
if (mddev->degraded != (mddev->raid_disks>>1)) {
printk(KERN_ERR "md/raid0:%s: All mirrors must be already degraded!\n",
mdname(mddev));
return ERR_PTR(-EINVAL);
}
/* Set new parameters */
mddev->new_level = 0;
mddev->new_chunk_sectors = mddev->chunk_sectors;
mddev->delta_disks = - mddev->raid_disks / 2;
mddev->raid_disks += mddev->delta_disks;
mddev->degraded = 0;
/* make sure it will be not marked as dirty */
mddev->recovery_cp = MaxSector;
create_strip_zones(mddev, &priv_conf);
priv_conf->scale_raid_disks = 2;
return priv_conf;
}
static void *raid0_takeover(mddev_t *mddev)
{
/* raid0 can take over:
* raid5 - providing it is Raid4 layout and one disk is faulty
* raid10 - assuming we have all necessary active disks
*/
if (mddev->level == 5) {
if (mddev->layout == ALGORITHM_PARITY_N)
return raid0_takeover_raid5(mddev);
printk(KERN_ERR "md/raid0:%s: Raid can only takeover Raid5 with layout: %d\n",
mdname(mddev), ALGORITHM_PARITY_N);
}
if (mddev->level == 10)
return raid0_takeover_raid10(mddev);
return ERR_PTR(-EINVAL);
}
static void raid0_quiesce(mddev_t *mddev, int state)
{
}
static struct mdk_personality raid0_personality= static struct mdk_personality raid0_personality=
{ {
.name = "raid0", .name = "raid0",
...@@ -554,6 +681,8 @@ static struct mdk_personality raid0_personality= ...@@ -554,6 +681,8 @@ static struct mdk_personality raid0_personality=
.stop = raid0_stop, .stop = raid0_stop,
.status = raid0_status, .status = raid0_status,
.size = raid0_size, .size = raid0_size,
.takeover = raid0_takeover,
.quiesce = raid0_quiesce,
}; };
static int __init raid0_init (void) static int __init raid0_init (void)
......
...@@ -13,6 +13,9 @@ struct raid0_private_data ...@@ -13,6 +13,9 @@ struct raid0_private_data
struct strip_zone *strip_zone; struct strip_zone *strip_zone;
mdk_rdev_t **devlist; /* lists of rdevs, pointed to by strip_zone->dev */ mdk_rdev_t **devlist; /* lists of rdevs, pointed to by strip_zone->dev */
int nr_strip_zones; int nr_strip_zones;
int scale_raid_disks; /* divide rdev->raid_disks by this in run()
* to handle conversion from raid10
*/
}; };
typedef struct raid0_private_data raid0_conf_t; typedef struct raid0_private_data raid0_conf_t;
......
...@@ -263,7 +263,7 @@ static inline void update_head_pos(int disk, r1bio_t *r1_bio) ...@@ -263,7 +263,7 @@ static inline void update_head_pos(int disk, r1bio_t *r1_bio)
static void raid1_end_read_request(struct bio *bio, int error) static void raid1_end_read_request(struct bio *bio, int error)
{ {
int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags); int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags);
r1bio_t * r1_bio = (r1bio_t *)(bio->bi_private); r1bio_t *r1_bio = bio->bi_private;
int mirror; int mirror;
conf_t *conf = r1_bio->mddev->private; conf_t *conf = r1_bio->mddev->private;
...@@ -297,7 +297,8 @@ static void raid1_end_read_request(struct bio *bio, int error) ...@@ -297,7 +297,8 @@ static void raid1_end_read_request(struct bio *bio, int error)
*/ */
char b[BDEVNAME_SIZE]; char b[BDEVNAME_SIZE];
if (printk_ratelimit()) if (printk_ratelimit())
printk(KERN_ERR "raid1: %s: rescheduling sector %llu\n", printk(KERN_ERR "md/raid1:%s: %s: rescheduling sector %llu\n",
mdname(conf->mddev),
bdevname(conf->mirrors[mirror].rdev->bdev,b), (unsigned long long)r1_bio->sector); bdevname(conf->mirrors[mirror].rdev->bdev,b), (unsigned long long)r1_bio->sector);
reschedule_retry(r1_bio); reschedule_retry(r1_bio);
} }
...@@ -308,7 +309,7 @@ static void raid1_end_read_request(struct bio *bio, int error) ...@@ -308,7 +309,7 @@ static void raid1_end_read_request(struct bio *bio, int error)
static void raid1_end_write_request(struct bio *bio, int error) static void raid1_end_write_request(struct bio *bio, int error)
{ {
int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags); int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags);
r1bio_t * r1_bio = (r1bio_t *)(bio->bi_private); r1bio_t *r1_bio = bio->bi_private;
int mirror, behind = test_bit(R1BIO_BehindIO, &r1_bio->state); int mirror, behind = test_bit(R1BIO_BehindIO, &r1_bio->state);
conf_t *conf = r1_bio->mddev->private; conf_t *conf = r1_bio->mddev->private;
struct bio *to_put = NULL; struct bio *to_put = NULL;
...@@ -418,7 +419,7 @@ static void raid1_end_write_request(struct bio *bio, int error) ...@@ -418,7 +419,7 @@ static void raid1_end_write_request(struct bio *bio, int error)
*/ */
static int read_balance(conf_t *conf, r1bio_t *r1_bio) static int read_balance(conf_t *conf, r1bio_t *r1_bio)
{ {
const unsigned long this_sector = r1_bio->sector; const sector_t this_sector = r1_bio->sector;
int new_disk = conf->last_used, disk = new_disk; int new_disk = conf->last_used, disk = new_disk;
int wonly_disk = -1; int wonly_disk = -1;
const int sectors = r1_bio->sectors; const int sectors = r1_bio->sectors;
...@@ -434,7 +435,7 @@ static int read_balance(conf_t *conf, r1bio_t *r1_bio) ...@@ -434,7 +435,7 @@ static int read_balance(conf_t *conf, r1bio_t *r1_bio)
retry: retry:
if (conf->mddev->recovery_cp < MaxSector && if (conf->mddev->recovery_cp < MaxSector &&
(this_sector + sectors >= conf->next_resync)) { (this_sector + sectors >= conf->next_resync)) {
/* Choose the first operation device, for consistancy */ /* Choose the first operational device, for consistancy */
new_disk = 0; new_disk = 0;
for (rdev = rcu_dereference(conf->mirrors[new_disk].rdev); for (rdev = rcu_dereference(conf->mirrors[new_disk].rdev);
...@@ -774,9 +775,8 @@ static struct page **alloc_behind_pages(struct bio *bio) ...@@ -774,9 +775,8 @@ static struct page **alloc_behind_pages(struct bio *bio)
return NULL; return NULL;
} }
static int make_request(struct request_queue *q, struct bio * bio) static int make_request(mddev_t *mddev, struct bio * bio)
{ {
mddev_t *mddev = q->queuedata;
conf_t *conf = mddev->private; conf_t *conf = mddev->private;
mirror_info_t *mirror; mirror_info_t *mirror;
r1bio_t *r1_bio; r1bio_t *r1_bio;
...@@ -788,7 +788,6 @@ static int make_request(struct request_queue *q, struct bio * bio) ...@@ -788,7 +788,6 @@ static int make_request(struct request_queue *q, struct bio * bio)
struct page **behind_pages = NULL; struct page **behind_pages = NULL;
const int rw = bio_data_dir(bio); const int rw = bio_data_dir(bio);
const bool do_sync = bio_rw_flagged(bio, BIO_RW_SYNCIO); const bool do_sync = bio_rw_flagged(bio, BIO_RW_SYNCIO);
int cpu;
bool do_barriers; bool do_barriers;
mdk_rdev_t *blocked_rdev; mdk_rdev_t *blocked_rdev;
...@@ -834,12 +833,6 @@ static int make_request(struct request_queue *q, struct bio * bio) ...@@ -834,12 +833,6 @@ static int make_request(struct request_queue *q, struct bio * bio)
bitmap = mddev->bitmap; bitmap = mddev->bitmap;
cpu = part_stat_lock();
part_stat_inc(cpu, &mddev->gendisk->part0, ios[rw]);
part_stat_add(cpu, &mddev->gendisk->part0, sectors[rw],
bio_sectors(bio));
part_stat_unlock();
/* /*
* make_request() can abort the operation when READA is being * make_request() can abort the operation when READA is being
* used and no empty request is available. * used and no empty request is available.
...@@ -866,6 +859,15 @@ static int make_request(struct request_queue *q, struct bio * bio) ...@@ -866,6 +859,15 @@ static int make_request(struct request_queue *q, struct bio * bio)
} }
mirror = conf->mirrors + rdisk; mirror = conf->mirrors + rdisk;
if (test_bit(WriteMostly, &mirror->rdev->flags) &&
bitmap) {
/* Reading from a write-mostly device must
* take care not to over-take any writes
* that are 'behind'
*/
wait_event(bitmap->behind_wait,
atomic_read(&bitmap->behind_writes) == 0);
}
r1_bio->read_disk = rdisk; r1_bio->read_disk = rdisk;
read_bio = bio_clone(bio, GFP_NOIO); read_bio = bio_clone(bio, GFP_NOIO);
...@@ -912,9 +914,10 @@ static int make_request(struct request_queue *q, struct bio * bio) ...@@ -912,9 +914,10 @@ static int make_request(struct request_queue *q, struct bio * bio)
if (test_bit(Faulty, &rdev->flags)) { if (test_bit(Faulty, &rdev->flags)) {
rdev_dec_pending(rdev, mddev); rdev_dec_pending(rdev, mddev);
r1_bio->bios[i] = NULL; r1_bio->bios[i] = NULL;
} else } else {
r1_bio->bios[i] = bio; r1_bio->bios[i] = bio;
targets++; targets++;
}
} else } else
r1_bio->bios[i] = NULL; r1_bio->bios[i] = NULL;
} }
...@@ -942,10 +945,14 @@ static int make_request(struct request_queue *q, struct bio * bio) ...@@ -942,10 +945,14 @@ static int make_request(struct request_queue *q, struct bio * bio)
set_bit(R1BIO_Degraded, &r1_bio->state); set_bit(R1BIO_Degraded, &r1_bio->state);
} }
/* do behind I/O ? */ /* do behind I/O ?
* Not if there are too many, or cannot allocate memory,
* or a reader on WriteMostly is waiting for behind writes
* to flush */
if (bitmap && if (bitmap &&
(atomic_read(&bitmap->behind_writes) (atomic_read(&bitmap->behind_writes)
< mddev->bitmap_info.max_write_behind) && < mddev->bitmap_info.max_write_behind) &&
!waitqueue_active(&bitmap->behind_wait) &&
(behind_pages = alloc_behind_pages(bio)) != NULL) (behind_pages = alloc_behind_pages(bio)) != NULL)
set_bit(R1BIO_BehindIO, &r1_bio->state); set_bit(R1BIO_BehindIO, &r1_bio->state);
...@@ -1070,21 +1077,22 @@ static void error(mddev_t *mddev, mdk_rdev_t *rdev) ...@@ -1070,21 +1077,22 @@ static void error(mddev_t *mddev, mdk_rdev_t *rdev)
} else } else
set_bit(Faulty, &rdev->flags); set_bit(Faulty, &rdev->flags);
set_bit(MD_CHANGE_DEVS, &mddev->flags); set_bit(MD_CHANGE_DEVS, &mddev->flags);
printk(KERN_ALERT "raid1: Disk failure on %s, disabling device.\n" printk(KERN_ALERT "md/raid1:%s: Disk failure on %s, disabling device.\n"
"raid1: Operation continuing on %d devices.\n", KERN_ALERT "md/raid1:%s: Operation continuing on %d devices.\n",
bdevname(rdev->bdev,b), conf->raid_disks - mddev->degraded); mdname(mddev), bdevname(rdev->bdev, b),
mdname(mddev), conf->raid_disks - mddev->degraded);
} }
static void print_conf(conf_t *conf) static void print_conf(conf_t *conf)
{ {
int i; int i;
printk("RAID1 conf printout:\n"); printk(KERN_DEBUG "RAID1 conf printout:\n");
if (!conf) { if (!conf) {
printk("(!conf)\n"); printk(KERN_DEBUG "(!conf)\n");
return; return;
} }
printk(" --- wd:%d rd:%d\n", conf->raid_disks - conf->mddev->degraded, printk(KERN_DEBUG " --- wd:%d rd:%d\n", conf->raid_disks - conf->mddev->degraded,
conf->raid_disks); conf->raid_disks);
rcu_read_lock(); rcu_read_lock();
...@@ -1092,7 +1100,7 @@ static void print_conf(conf_t *conf) ...@@ -1092,7 +1100,7 @@ static void print_conf(conf_t *conf)
char b[BDEVNAME_SIZE]; char b[BDEVNAME_SIZE];
mdk_rdev_t *rdev = rcu_dereference(conf->mirrors[i].rdev); mdk_rdev_t *rdev = rcu_dereference(conf->mirrors[i].rdev);
if (rdev) if (rdev)
printk(" disk %d, wo:%d, o:%d, dev:%s\n", printk(KERN_DEBUG " disk %d, wo:%d, o:%d, dev:%s\n",
i, !test_bit(In_sync, &rdev->flags), i, !test_bit(In_sync, &rdev->flags),
!test_bit(Faulty, &rdev->flags), !test_bit(Faulty, &rdev->flags),
bdevname(rdev->bdev,b)); bdevname(rdev->bdev,b));
...@@ -1223,7 +1231,7 @@ static int raid1_remove_disk(mddev_t *mddev, int number) ...@@ -1223,7 +1231,7 @@ static int raid1_remove_disk(mddev_t *mddev, int number)
static void end_sync_read(struct bio *bio, int error) static void end_sync_read(struct bio *bio, int error)
{ {
r1bio_t * r1_bio = (r1bio_t *)(bio->bi_private); r1bio_t *r1_bio = bio->bi_private;
int i; int i;
for (i=r1_bio->mddev->raid_disks; i--; ) for (i=r1_bio->mddev->raid_disks; i--; )
...@@ -1246,7 +1254,7 @@ static void end_sync_read(struct bio *bio, int error) ...@@ -1246,7 +1254,7 @@ static void end_sync_read(struct bio *bio, int error)
static void end_sync_write(struct bio *bio, int error) static void end_sync_write(struct bio *bio, int error)
{ {
int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags); int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags);
r1bio_t * r1_bio = (r1bio_t *)(bio->bi_private); r1bio_t *r1_bio = bio->bi_private;
mddev_t *mddev = r1_bio->mddev; mddev_t *mddev = r1_bio->mddev;
conf_t *conf = mddev->private; conf_t *conf = mddev->private;
int i; int i;
...@@ -1453,9 +1461,10 @@ static void sync_request_write(mddev_t *mddev, r1bio_t *r1_bio) ...@@ -1453,9 +1461,10 @@ static void sync_request_write(mddev_t *mddev, r1bio_t *r1_bio)
char b[BDEVNAME_SIZE]; char b[BDEVNAME_SIZE];
/* Cannot read from anywhere, array is toast */ /* Cannot read from anywhere, array is toast */
md_error(mddev, conf->mirrors[r1_bio->read_disk].rdev); md_error(mddev, conf->mirrors[r1_bio->read_disk].rdev);
printk(KERN_ALERT "raid1: %s: unrecoverable I/O read error" printk(KERN_ALERT "md/raid1:%s: %s: unrecoverable I/O read error"
" for block %llu\n", " for block %llu\n",
bdevname(bio->bi_bdev,b), mdname(mddev),
bdevname(bio->bi_bdev, b),
(unsigned long long)r1_bio->sector); (unsigned long long)r1_bio->sector);
md_done_sync(mddev, r1_bio->sectors, 0); md_done_sync(mddev, r1_bio->sectors, 0);
put_buf(r1_bio); put_buf(r1_bio);
...@@ -1577,7 +1586,7 @@ static void fix_read_error(conf_t *conf, int read_disk, ...@@ -1577,7 +1586,7 @@ static void fix_read_error(conf_t *conf, int read_disk,
else { else {
atomic_add(s, &rdev->corrected_errors); atomic_add(s, &rdev->corrected_errors);
printk(KERN_INFO printk(KERN_INFO
"raid1:%s: read error corrected " "md/raid1:%s: read error corrected "
"(%d sectors at %llu on %s)\n", "(%d sectors at %llu on %s)\n",
mdname(mddev), s, mdname(mddev), s,
(unsigned long long)(sect + (unsigned long long)(sect +
...@@ -1682,8 +1691,9 @@ static void raid1d(mddev_t *mddev) ...@@ -1682,8 +1691,9 @@ static void raid1d(mddev_t *mddev)
bio = r1_bio->bios[r1_bio->read_disk]; bio = r1_bio->bios[r1_bio->read_disk];
if ((disk=read_balance(conf, r1_bio)) == -1) { if ((disk=read_balance(conf, r1_bio)) == -1) {
printk(KERN_ALERT "raid1: %s: unrecoverable I/O" printk(KERN_ALERT "md/raid1:%s: %s: unrecoverable I/O"
" read error for block %llu\n", " read error for block %llu\n",
mdname(mddev),
bdevname(bio->bi_bdev,b), bdevname(bio->bi_bdev,b),
(unsigned long long)r1_bio->sector); (unsigned long long)r1_bio->sector);
raid_end_bio_io(r1_bio); raid_end_bio_io(r1_bio);
...@@ -1697,10 +1707,11 @@ static void raid1d(mddev_t *mddev) ...@@ -1697,10 +1707,11 @@ static void raid1d(mddev_t *mddev)
r1_bio->bios[r1_bio->read_disk] = bio; r1_bio->bios[r1_bio->read_disk] = bio;
rdev = conf->mirrors[disk].rdev; rdev = conf->mirrors[disk].rdev;
if (printk_ratelimit()) if (printk_ratelimit())
printk(KERN_ERR "raid1: %s: redirecting sector %llu to" printk(KERN_ERR "md/raid1:%s: redirecting sector %llu to"
" another mirror\n", " other mirror: %s\n",
bdevname(rdev->bdev,b), mdname(mddev),
(unsigned long long)r1_bio->sector); (unsigned long long)r1_bio->sector,
bdevname(rdev->bdev,b));
bio->bi_sector = r1_bio->sector + rdev->data_offset; bio->bi_sector = r1_bio->sector + rdev->data_offset;
bio->bi_bdev = rdev->bdev; bio->bi_bdev = rdev->bdev;
bio->bi_end_io = raid1_end_read_request; bio->bi_end_io = raid1_end_read_request;
...@@ -1755,13 +1766,8 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i ...@@ -1755,13 +1766,8 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i
int still_degraded = 0; int still_degraded = 0;
if (!conf->r1buf_pool) if (!conf->r1buf_pool)
{
/*
printk("sync start - bitmap %p\n", mddev->bitmap);
*/
if (init_resync(conf)) if (init_resync(conf))
return 0; return 0;
}
max_sector = mddev->dev_sectors; max_sector = mddev->dev_sectors;
if (sector_nr >= max_sector) { if (sector_nr >= max_sector) {
...@@ -2042,7 +2048,7 @@ static conf_t *setup_conf(mddev_t *mddev) ...@@ -2042,7 +2048,7 @@ static conf_t *setup_conf(mddev_t *mddev)
err = -EIO; err = -EIO;
if (conf->last_used < 0) { if (conf->last_used < 0) {
printk(KERN_ERR "raid1: no operational mirrors for %s\n", printk(KERN_ERR "md/raid1:%s: no operational mirrors\n",
mdname(mddev)); mdname(mddev));
goto abort; goto abort;
} }
...@@ -2050,7 +2056,7 @@ static conf_t *setup_conf(mddev_t *mddev) ...@@ -2050,7 +2056,7 @@ static conf_t *setup_conf(mddev_t *mddev)
conf->thread = md_register_thread(raid1d, mddev, NULL); conf->thread = md_register_thread(raid1d, mddev, NULL);
if (!conf->thread) { if (!conf->thread) {
printk(KERN_ERR printk(KERN_ERR
"raid1: couldn't allocate thread for %s\n", "md/raid1:%s: couldn't allocate thread\n",
mdname(mddev)); mdname(mddev));
goto abort; goto abort;
} }
...@@ -2076,12 +2082,12 @@ static int run(mddev_t *mddev) ...@@ -2076,12 +2082,12 @@ static int run(mddev_t *mddev)
mdk_rdev_t *rdev; mdk_rdev_t *rdev;
if (mddev->level != 1) { if (mddev->level != 1) {
printk("raid1: %s: raid level not set to mirroring (%d)\n", printk(KERN_ERR "md/raid1:%s: raid level not set to mirroring (%d)\n",
mdname(mddev), mddev->level); mdname(mddev), mddev->level);
return -EIO; return -EIO;
} }
if (mddev->reshape_position != MaxSector) { if (mddev->reshape_position != MaxSector) {
printk("raid1: %s: reshape_position set but not supported\n", printk(KERN_ERR "md/raid1:%s: reshape_position set but not supported\n",
mdname(mddev)); mdname(mddev));
return -EIO; return -EIO;
} }
...@@ -2124,11 +2130,11 @@ static int run(mddev_t *mddev) ...@@ -2124,11 +2130,11 @@ static int run(mddev_t *mddev)
mddev->recovery_cp = MaxSector; mddev->recovery_cp = MaxSector;
if (mddev->recovery_cp != MaxSector) if (mddev->recovery_cp != MaxSector)
printk(KERN_NOTICE "raid1: %s is not clean" printk(KERN_NOTICE "md/raid1:%s: not clean"
" -- starting background reconstruction\n", " -- starting background reconstruction\n",
mdname(mddev)); mdname(mddev));
printk(KERN_INFO printk(KERN_INFO
"raid1: raid set %s active with %d out of %d mirrors\n", "md/raid1:%s: active with %d out of %d mirrors\n",
mdname(mddev), mddev->raid_disks - mddev->degraded, mdname(mddev), mddev->raid_disks - mddev->degraded,
mddev->raid_disks); mddev->raid_disks);
...@@ -2152,15 +2158,14 @@ static int stop(mddev_t *mddev) ...@@ -2152,15 +2158,14 @@ static int stop(mddev_t *mddev)
{ {
conf_t *conf = mddev->private; conf_t *conf = mddev->private;
struct bitmap *bitmap = mddev->bitmap; struct bitmap *bitmap = mddev->bitmap;
int behind_wait = 0;
/* wait for behind writes to complete */ /* wait for behind writes to complete */
while (bitmap && atomic_read(&bitmap->behind_writes) > 0) { if (bitmap && atomic_read(&bitmap->behind_writes) > 0) {
behind_wait++; printk(KERN_INFO "md/raid1:%s: behind writes in progress - waiting to stop.\n",
printk(KERN_INFO "raid1: behind writes in progress on device %s, waiting to stop (%d)\n", mdname(mddev), behind_wait); mdname(mddev));
set_current_state(TASK_UNINTERRUPTIBLE);
schedule_timeout(HZ); /* wait a second */
/* need to kick something here to make sure I/O goes? */ /* need to kick something here to make sure I/O goes? */
wait_event(bitmap->behind_wait,
atomic_read(&bitmap->behind_writes) == 0);
} }
raise_barrier(conf); raise_barrier(conf);
...@@ -2191,7 +2196,6 @@ static int raid1_resize(mddev_t *mddev, sector_t sectors) ...@@ -2191,7 +2196,6 @@ static int raid1_resize(mddev_t *mddev, sector_t sectors)
if (mddev->array_sectors > raid1_size(mddev, sectors, 0)) if (mddev->array_sectors > raid1_size(mddev, sectors, 0))
return -EINVAL; return -EINVAL;
set_capacity(mddev->gendisk, mddev->array_sectors); set_capacity(mddev->gendisk, mddev->array_sectors);
mddev->changed = 1;
revalidate_disk(mddev->gendisk); revalidate_disk(mddev->gendisk);
if (sectors > mddev->dev_sectors && if (sectors > mddev->dev_sectors &&
mddev->recovery_cp == MaxSector) { mddev->recovery_cp == MaxSector) {
...@@ -2286,9 +2290,9 @@ static int raid1_reshape(mddev_t *mddev) ...@@ -2286,9 +2290,9 @@ static int raid1_reshape(mddev_t *mddev)
if (sysfs_create_link(&mddev->kobj, if (sysfs_create_link(&mddev->kobj,
&rdev->kobj, nm)) &rdev->kobj, nm))
printk(KERN_WARNING printk(KERN_WARNING
"md/raid1: cannot register " "md/raid1:%s: cannot register "
"%s for %s\n", "%s\n",
nm, mdname(mddev)); mdname(mddev), nm);
} }
if (rdev) if (rdev)
newmirrors[d2++].rdev = rdev; newmirrors[d2++].rdev = rdev;
......
...@@ -24,6 +24,7 @@ ...@@ -24,6 +24,7 @@
#include <linux/seq_file.h> #include <linux/seq_file.h>
#include "md.h" #include "md.h"
#include "raid10.h" #include "raid10.h"
#include "raid0.h"
#include "bitmap.h" #include "bitmap.h"
/* /*
...@@ -255,7 +256,7 @@ static inline void update_head_pos(int slot, r10bio_t *r10_bio) ...@@ -255,7 +256,7 @@ static inline void update_head_pos(int slot, r10bio_t *r10_bio)
static void raid10_end_read_request(struct bio *bio, int error) static void raid10_end_read_request(struct bio *bio, int error)
{ {
int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags); int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags);
r10bio_t * r10_bio = (r10bio_t *)(bio->bi_private); r10bio_t *r10_bio = bio->bi_private;
int slot, dev; int slot, dev;
conf_t *conf = r10_bio->mddev->private; conf_t *conf = r10_bio->mddev->private;
...@@ -285,7 +286,8 @@ static void raid10_end_read_request(struct bio *bio, int error) ...@@ -285,7 +286,8 @@ static void raid10_end_read_request(struct bio *bio, int error)
*/ */
char b[BDEVNAME_SIZE]; char b[BDEVNAME_SIZE];
if (printk_ratelimit()) if (printk_ratelimit())
printk(KERN_ERR "raid10: %s: rescheduling sector %llu\n", printk(KERN_ERR "md/raid10:%s: %s: rescheduling sector %llu\n",
mdname(conf->mddev),
bdevname(conf->mirrors[dev].rdev->bdev,b), (unsigned long long)r10_bio->sector); bdevname(conf->mirrors[dev].rdev->bdev,b), (unsigned long long)r10_bio->sector);
reschedule_retry(r10_bio); reschedule_retry(r10_bio);
} }
...@@ -296,7 +298,7 @@ static void raid10_end_read_request(struct bio *bio, int error) ...@@ -296,7 +298,7 @@ static void raid10_end_read_request(struct bio *bio, int error)
static void raid10_end_write_request(struct bio *bio, int error) static void raid10_end_write_request(struct bio *bio, int error)
{ {
int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags); int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags);
r10bio_t * r10_bio = (r10bio_t *)(bio->bi_private); r10bio_t *r10_bio = bio->bi_private;
int slot, dev; int slot, dev;
conf_t *conf = r10_bio->mddev->private; conf_t *conf = r10_bio->mddev->private;
...@@ -494,7 +496,7 @@ static int raid10_mergeable_bvec(struct request_queue *q, ...@@ -494,7 +496,7 @@ static int raid10_mergeable_bvec(struct request_queue *q,
*/ */
static int read_balance(conf_t *conf, r10bio_t *r10_bio) static int read_balance(conf_t *conf, r10bio_t *r10_bio)
{ {
const unsigned long this_sector = r10_bio->sector; const sector_t this_sector = r10_bio->sector;
int disk, slot, nslot; int disk, slot, nslot;
const int sectors = r10_bio->sectors; const int sectors = r10_bio->sectors;
sector_t new_distance, current_distance; sector_t new_distance, current_distance;
...@@ -601,7 +603,7 @@ static void unplug_slaves(mddev_t *mddev) ...@@ -601,7 +603,7 @@ static void unplug_slaves(mddev_t *mddev)
int i; int i;
rcu_read_lock(); rcu_read_lock();
for (i=0; i<mddev->raid_disks; i++) { for (i=0; i < conf->raid_disks; i++) {
mdk_rdev_t *rdev = rcu_dereference(conf->mirrors[i].rdev); mdk_rdev_t *rdev = rcu_dereference(conf->mirrors[i].rdev);
if (rdev && !test_bit(Faulty, &rdev->flags) && atomic_read(&rdev->nr_pending)) { if (rdev && !test_bit(Faulty, &rdev->flags) && atomic_read(&rdev->nr_pending)) {
struct request_queue *r_queue = bdev_get_queue(rdev->bdev); struct request_queue *r_queue = bdev_get_queue(rdev->bdev);
...@@ -635,7 +637,7 @@ static int raid10_congested(void *data, int bits) ...@@ -635,7 +637,7 @@ static int raid10_congested(void *data, int bits)
if (mddev_congested(mddev, bits)) if (mddev_congested(mddev, bits))
return 1; return 1;
rcu_read_lock(); rcu_read_lock();
for (i = 0; i < mddev->raid_disks && ret == 0; i++) { for (i = 0; i < conf->raid_disks && ret == 0; i++) {
mdk_rdev_t *rdev = rcu_dereference(conf->mirrors[i].rdev); mdk_rdev_t *rdev = rcu_dereference(conf->mirrors[i].rdev);
if (rdev && !test_bit(Faulty, &rdev->flags)) { if (rdev && !test_bit(Faulty, &rdev->flags)) {
struct request_queue *q = bdev_get_queue(rdev->bdev); struct request_queue *q = bdev_get_queue(rdev->bdev);
...@@ -788,14 +790,12 @@ static void unfreeze_array(conf_t *conf) ...@@ -788,14 +790,12 @@ static void unfreeze_array(conf_t *conf)
spin_unlock_irq(&conf->resync_lock); spin_unlock_irq(&conf->resync_lock);
} }
static int make_request(struct request_queue *q, struct bio * bio) static int make_request(mddev_t *mddev, struct bio * bio)
{ {
mddev_t *mddev = q->queuedata;
conf_t *conf = mddev->private; conf_t *conf = mddev->private;
mirror_info_t *mirror; mirror_info_t *mirror;
r10bio_t *r10_bio; r10bio_t *r10_bio;
struct bio *read_bio; struct bio *read_bio;
int cpu;
int i; int i;
int chunk_sects = conf->chunk_mask + 1; int chunk_sects = conf->chunk_mask + 1;
const int rw = bio_data_dir(bio); const int rw = bio_data_dir(bio);
...@@ -825,16 +825,16 @@ static int make_request(struct request_queue *q, struct bio * bio) ...@@ -825,16 +825,16 @@ static int make_request(struct request_queue *q, struct bio * bio)
*/ */
bp = bio_split(bio, bp = bio_split(bio,
chunk_sects - (bio->bi_sector & (chunk_sects - 1)) ); chunk_sects - (bio->bi_sector & (chunk_sects - 1)) );
if (make_request(q, &bp->bio1)) if (make_request(mddev, &bp->bio1))
generic_make_request(&bp->bio1); generic_make_request(&bp->bio1);
if (make_request(q, &bp->bio2)) if (make_request(mddev, &bp->bio2))
generic_make_request(&bp->bio2); generic_make_request(&bp->bio2);
bio_pair_release(bp); bio_pair_release(bp);
return 0; return 0;
bad_map: bad_map:
printk("raid10_make_request bug: can't convert block across chunks" printk("md/raid10:%s: make_request bug: can't convert block across chunks"
" or bigger than %dk %llu %d\n", chunk_sects/2, " or bigger than %dk %llu %d\n", mdname(mddev), chunk_sects/2,
(unsigned long long)bio->bi_sector, bio->bi_size >> 10); (unsigned long long)bio->bi_sector, bio->bi_size >> 10);
bio_io_error(bio); bio_io_error(bio);
...@@ -850,12 +850,6 @@ static int make_request(struct request_queue *q, struct bio * bio) ...@@ -850,12 +850,6 @@ static int make_request(struct request_queue *q, struct bio * bio)
*/ */
wait_barrier(conf); wait_barrier(conf);
cpu = part_stat_lock();
part_stat_inc(cpu, &mddev->gendisk->part0, ios[rw]);
part_stat_add(cpu, &mddev->gendisk->part0, sectors[rw],
bio_sectors(bio));
part_stat_unlock();
r10_bio = mempool_alloc(conf->r10bio_pool, GFP_NOIO); r10_bio = mempool_alloc(conf->r10bio_pool, GFP_NOIO);
r10_bio->master_bio = bio; r10_bio->master_bio = bio;
...@@ -1039,9 +1033,10 @@ static void error(mddev_t *mddev, mdk_rdev_t *rdev) ...@@ -1039,9 +1033,10 @@ static void error(mddev_t *mddev, mdk_rdev_t *rdev)
} }
set_bit(Faulty, &rdev->flags); set_bit(Faulty, &rdev->flags);
set_bit(MD_CHANGE_DEVS, &mddev->flags); set_bit(MD_CHANGE_DEVS, &mddev->flags);
printk(KERN_ALERT "raid10: Disk failure on %s, disabling device.\n" printk(KERN_ALERT "md/raid10:%s: Disk failure on %s, disabling device.\n"
"raid10: Operation continuing on %d devices.\n", KERN_ALERT "md/raid10:%s: Operation continuing on %d devices.\n",
bdevname(rdev->bdev,b), conf->raid_disks - mddev->degraded); mdname(mddev), bdevname(rdev->bdev, b),
mdname(mddev), conf->raid_disks - mddev->degraded);
} }
static void print_conf(conf_t *conf) static void print_conf(conf_t *conf)
...@@ -1049,19 +1044,19 @@ static void print_conf(conf_t *conf) ...@@ -1049,19 +1044,19 @@ static void print_conf(conf_t *conf)
int i; int i;
mirror_info_t *tmp; mirror_info_t *tmp;
printk("RAID10 conf printout:\n"); printk(KERN_DEBUG "RAID10 conf printout:\n");
if (!conf) { if (!conf) {
printk("(!conf)\n"); printk(KERN_DEBUG "(!conf)\n");
return; return;
} }
printk(" --- wd:%d rd:%d\n", conf->raid_disks - conf->mddev->degraded, printk(KERN_DEBUG " --- wd:%d rd:%d\n", conf->raid_disks - conf->mddev->degraded,
conf->raid_disks); conf->raid_disks);
for (i = 0; i < conf->raid_disks; i++) { for (i = 0; i < conf->raid_disks; i++) {
char b[BDEVNAME_SIZE]; char b[BDEVNAME_SIZE];
tmp = conf->mirrors + i; tmp = conf->mirrors + i;
if (tmp->rdev) if (tmp->rdev)
printk(" disk %d, wo:%d, o:%d, dev:%s\n", printk(KERN_DEBUG " disk %d, wo:%d, o:%d, dev:%s\n",
i, !test_bit(In_sync, &tmp->rdev->flags), i, !test_bit(In_sync, &tmp->rdev->flags),
!test_bit(Faulty, &tmp->rdev->flags), !test_bit(Faulty, &tmp->rdev->flags),
bdevname(tmp->rdev->bdev,b)); bdevname(tmp->rdev->bdev,b));
...@@ -1132,7 +1127,7 @@ static int raid10_add_disk(mddev_t *mddev, mdk_rdev_t *rdev) ...@@ -1132,7 +1127,7 @@ static int raid10_add_disk(mddev_t *mddev, mdk_rdev_t *rdev)
int mirror; int mirror;
mirror_info_t *p; mirror_info_t *p;
int first = 0; int first = 0;
int last = mddev->raid_disks - 1; int last = conf->raid_disks - 1;
if (mddev->recovery_cp < MaxSector) if (mddev->recovery_cp < MaxSector)
/* only hot-add to in-sync arrays, as recovery is /* only hot-add to in-sync arrays, as recovery is
...@@ -1224,7 +1219,7 @@ static int raid10_remove_disk(mddev_t *mddev, int number) ...@@ -1224,7 +1219,7 @@ static int raid10_remove_disk(mddev_t *mddev, int number)
static void end_sync_read(struct bio *bio, int error) static void end_sync_read(struct bio *bio, int error)
{ {
r10bio_t * r10_bio = (r10bio_t *)(bio->bi_private); r10bio_t *r10_bio = bio->bi_private;
conf_t *conf = r10_bio->mddev->private; conf_t *conf = r10_bio->mddev->private;
int i,d; int i,d;
...@@ -1261,7 +1256,7 @@ static void end_sync_read(struct bio *bio, int error) ...@@ -1261,7 +1256,7 @@ static void end_sync_read(struct bio *bio, int error)
static void end_sync_write(struct bio *bio, int error) static void end_sync_write(struct bio *bio, int error)
{ {
int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags); int uptodate = test_bit(BIO_UPTODATE, &bio->bi_flags);
r10bio_t * r10_bio = (r10bio_t *)(bio->bi_private); r10bio_t *r10_bio = bio->bi_private;
mddev_t *mddev = r10_bio->mddev; mddev_t *mddev = r10_bio->mddev;
conf_t *conf = mddev->private; conf_t *conf = mddev->private;
int i,d; int i,d;
...@@ -1510,13 +1505,14 @@ static void fix_read_error(conf_t *conf, mddev_t *mddev, r10bio_t *r10_bio) ...@@ -1510,13 +1505,14 @@ static void fix_read_error(conf_t *conf, mddev_t *mddev, r10bio_t *r10_bio)
if (cur_read_error_count > max_read_errors) { if (cur_read_error_count > max_read_errors) {
rcu_read_unlock(); rcu_read_unlock();
printk(KERN_NOTICE printk(KERN_NOTICE
"raid10: %s: Raid device exceeded " "md/raid10:%s: %s: Raid device exceeded "
"read_error threshold " "read_error threshold "
"[cur %d:max %d]\n", "[cur %d:max %d]\n",
mdname(mddev),
b, cur_read_error_count, max_read_errors); b, cur_read_error_count, max_read_errors);
printk(KERN_NOTICE printk(KERN_NOTICE
"raid10: %s: Failing raid " "md/raid10:%s: %s: Failing raid "
"device\n", b); "device\n", mdname(mddev), b);
md_error(mddev, conf->mirrors[d].rdev); md_error(mddev, conf->mirrors[d].rdev);
return; return;
} }
...@@ -1586,15 +1582,16 @@ static void fix_read_error(conf_t *conf, mddev_t *mddev, r10bio_t *r10_bio) ...@@ -1586,15 +1582,16 @@ static void fix_read_error(conf_t *conf, mddev_t *mddev, r10bio_t *r10_bio)
== 0) { == 0) {
/* Well, this device is dead */ /* Well, this device is dead */
printk(KERN_NOTICE printk(KERN_NOTICE
"raid10:%s: read correction " "md/raid10:%s: read correction "
"write failed" "write failed"
" (%d sectors at %llu on %s)\n", " (%d sectors at %llu on %s)\n",
mdname(mddev), s, mdname(mddev), s,
(unsigned long long)(sect+ (unsigned long long)(sect+
rdev->data_offset), rdev->data_offset),
bdevname(rdev->bdev, b)); bdevname(rdev->bdev, b));
printk(KERN_NOTICE "raid10:%s: failing " printk(KERN_NOTICE "md/raid10:%s: %s: failing "
"drive\n", "drive\n",
mdname(mddev),
bdevname(rdev->bdev, b)); bdevname(rdev->bdev, b));
md_error(mddev, rdev); md_error(mddev, rdev);
} }
...@@ -1622,20 +1619,21 @@ static void fix_read_error(conf_t *conf, mddev_t *mddev, r10bio_t *r10_bio) ...@@ -1622,20 +1619,21 @@ static void fix_read_error(conf_t *conf, mddev_t *mddev, r10bio_t *r10_bio)
READ) == 0) { READ) == 0) {
/* Well, this device is dead */ /* Well, this device is dead */
printk(KERN_NOTICE printk(KERN_NOTICE
"raid10:%s: unable to read back " "md/raid10:%s: unable to read back "
"corrected sectors" "corrected sectors"
" (%d sectors at %llu on %s)\n", " (%d sectors at %llu on %s)\n",
mdname(mddev), s, mdname(mddev), s,
(unsigned long long)(sect+ (unsigned long long)(sect+
rdev->data_offset), rdev->data_offset),
bdevname(rdev->bdev, b)); bdevname(rdev->bdev, b));
printk(KERN_NOTICE "raid10:%s: failing drive\n", printk(KERN_NOTICE "md/raid10:%s: %s: failing drive\n",
mdname(mddev),
bdevname(rdev->bdev, b)); bdevname(rdev->bdev, b));
md_error(mddev, rdev); md_error(mddev, rdev);
} else { } else {
printk(KERN_INFO printk(KERN_INFO
"raid10:%s: read error corrected" "md/raid10:%s: read error corrected"
" (%d sectors at %llu on %s)\n", " (%d sectors at %llu on %s)\n",
mdname(mddev), s, mdname(mddev), s,
(unsigned long long)(sect+ (unsigned long long)(sect+
...@@ -1710,8 +1708,9 @@ static void raid10d(mddev_t *mddev) ...@@ -1710,8 +1708,9 @@ static void raid10d(mddev_t *mddev)
mddev->ro ? IO_BLOCKED : NULL; mddev->ro ? IO_BLOCKED : NULL;
mirror = read_balance(conf, r10_bio); mirror = read_balance(conf, r10_bio);
if (mirror == -1) { if (mirror == -1) {
printk(KERN_ALERT "raid10: %s: unrecoverable I/O" printk(KERN_ALERT "md/raid10:%s: %s: unrecoverable I/O"
" read error for block %llu\n", " read error for block %llu\n",
mdname(mddev),
bdevname(bio->bi_bdev,b), bdevname(bio->bi_bdev,b),
(unsigned long long)r10_bio->sector); (unsigned long long)r10_bio->sector);
raid_end_bio_io(r10_bio); raid_end_bio_io(r10_bio);
...@@ -1721,8 +1720,9 @@ static void raid10d(mddev_t *mddev) ...@@ -1721,8 +1720,9 @@ static void raid10d(mddev_t *mddev)
bio_put(bio); bio_put(bio);
rdev = conf->mirrors[mirror].rdev; rdev = conf->mirrors[mirror].rdev;
if (printk_ratelimit()) if (printk_ratelimit())
printk(KERN_ERR "raid10: %s: redirecting sector %llu to" printk(KERN_ERR "md/raid10:%s: %s: redirecting sector %llu to"
" another mirror\n", " another mirror\n",
mdname(mddev),
bdevname(rdev->bdev,b), bdevname(rdev->bdev,b),
(unsigned long long)r10_bio->sector); (unsigned long long)r10_bio->sector);
bio = bio_clone(r10_bio->master_bio, GFP_NOIO); bio = bio_clone(r10_bio->master_bio, GFP_NOIO);
...@@ -1980,7 +1980,8 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i ...@@ -1980,7 +1980,8 @@ static sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *skipped, i
r10_bio = rb2; r10_bio = rb2;
if (!test_and_set_bit(MD_RECOVERY_INTR, if (!test_and_set_bit(MD_RECOVERY_INTR,
&mddev->recovery)) &mddev->recovery))
printk(KERN_INFO "raid10: %s: insufficient working devices for recovery.\n", printk(KERN_INFO "md/raid10:%s: insufficient "
"working devices for recovery.\n",
mdname(mddev)); mdname(mddev));
break; break;
} }
...@@ -2140,9 +2141,9 @@ raid10_size(mddev_t *mddev, sector_t sectors, int raid_disks) ...@@ -2140,9 +2141,9 @@ raid10_size(mddev_t *mddev, sector_t sectors, int raid_disks)
conf_t *conf = mddev->private; conf_t *conf = mddev->private;
if (!raid_disks) if (!raid_disks)
raid_disks = mddev->raid_disks; raid_disks = conf->raid_disks;
if (!sectors) if (!sectors)
sectors = mddev->dev_sectors; sectors = conf->dev_sectors;
size = sectors >> conf->chunk_shift; size = sectors >> conf->chunk_shift;
sector_div(size, conf->far_copies); sector_div(size, conf->far_copies);
...@@ -2152,62 +2153,61 @@ raid10_size(mddev_t *mddev, sector_t sectors, int raid_disks) ...@@ -2152,62 +2153,61 @@ raid10_size(mddev_t *mddev, sector_t sectors, int raid_disks)
return size << conf->chunk_shift; return size << conf->chunk_shift;
} }
static int run(mddev_t *mddev)
static conf_t *setup_conf(mddev_t *mddev)
{ {
conf_t *conf; conf_t *conf = NULL;
int i, disk_idx, chunk_size;
mirror_info_t *disk;
mdk_rdev_t *rdev;
int nc, fc, fo; int nc, fc, fo;
sector_t stride, size; sector_t stride, size;
int err = -EINVAL;
if (mddev->chunk_sectors < (PAGE_SIZE >> 9) || if (mddev->chunk_sectors < (PAGE_SIZE >> 9) ||
!is_power_of_2(mddev->chunk_sectors)) { !is_power_of_2(mddev->chunk_sectors)) {
printk(KERN_ERR "md/raid10: chunk size must be " printk(KERN_ERR "md/raid10:%s: chunk size must be "
"at least PAGE_SIZE(%ld) and be a power of 2.\n", PAGE_SIZE); "at least PAGE_SIZE(%ld) and be a power of 2.\n",
return -EINVAL; mdname(mddev), PAGE_SIZE);
goto out;
} }
nc = mddev->layout & 255; nc = mddev->layout & 255;
fc = (mddev->layout >> 8) & 255; fc = (mddev->layout >> 8) & 255;
fo = mddev->layout & (1<<16); fo = mddev->layout & (1<<16);
if ((nc*fc) <2 || (nc*fc) > mddev->raid_disks || if ((nc*fc) <2 || (nc*fc) > mddev->raid_disks ||
(mddev->layout >> 17)) { (mddev->layout >> 17)) {
printk(KERN_ERR "raid10: %s: unsupported raid10 layout: 0x%8x\n", printk(KERN_ERR "md/raid10:%s: unsupported raid10 layout: 0x%8x\n",
mdname(mddev), mddev->layout); mdname(mddev), mddev->layout);
goto out; goto out;
} }
/*
* copy the already verified devices into our private RAID10 err = -ENOMEM;
* bookkeeping area. [whatever we allocate in run(),
* should be freed in stop()]
*/
conf = kzalloc(sizeof(conf_t), GFP_KERNEL); conf = kzalloc(sizeof(conf_t), GFP_KERNEL);
mddev->private = conf; if (!conf)
if (!conf) {
printk(KERN_ERR "raid10: couldn't allocate memory for %s\n",
mdname(mddev));
goto out; goto out;
}
conf->mirrors = kzalloc(sizeof(struct mirror_info)*mddev->raid_disks, conf->mirrors = kzalloc(sizeof(struct mirror_info)*mddev->raid_disks,
GFP_KERNEL); GFP_KERNEL);
if (!conf->mirrors) { if (!conf->mirrors)
printk(KERN_ERR "raid10: couldn't allocate memory for %s\n", goto out;
mdname(mddev));
goto out_free_conf;
}
conf->tmppage = alloc_page(GFP_KERNEL); conf->tmppage = alloc_page(GFP_KERNEL);
if (!conf->tmppage) if (!conf->tmppage)
goto out_free_conf; goto out;
conf->raid_disks = mddev->raid_disks; conf->raid_disks = mddev->raid_disks;
conf->near_copies = nc; conf->near_copies = nc;
conf->far_copies = fc; conf->far_copies = fc;
conf->copies = nc*fc; conf->copies = nc*fc;
conf->far_offset = fo; conf->far_offset = fo;
conf->chunk_mask = mddev->chunk_sectors - 1; conf->chunk_mask = mddev->new_chunk_sectors - 1;
conf->chunk_shift = ffz(~mddev->chunk_sectors); conf->chunk_shift = ffz(~mddev->new_chunk_sectors);
conf->r10bio_pool = mempool_create(NR_RAID10_BIOS, r10bio_pool_alloc,
r10bio_pool_free, conf);
if (!conf->r10bio_pool)
goto out;
size = mddev->dev_sectors >> conf->chunk_shift; size = mddev->dev_sectors >> conf->chunk_shift;
sector_div(size, fc); sector_div(size, fc);
size = size * conf->raid_disks; size = size * conf->raid_disks;
...@@ -2221,7 +2221,8 @@ static int run(mddev_t *mddev) ...@@ -2221,7 +2221,8 @@ static int run(mddev_t *mddev)
*/ */
stride += conf->raid_disks - 1; stride += conf->raid_disks - 1;
sector_div(stride, conf->raid_disks); sector_div(stride, conf->raid_disks);
mddev->dev_sectors = stride << conf->chunk_shift;
conf->dev_sectors = stride << conf->chunk_shift;
if (fo) if (fo)
stride = 1; stride = 1;
...@@ -2229,18 +2230,63 @@ static int run(mddev_t *mddev) ...@@ -2229,18 +2230,63 @@ static int run(mddev_t *mddev)
sector_div(stride, fc); sector_div(stride, fc);
conf->stride = stride << conf->chunk_shift; conf->stride = stride << conf->chunk_shift;
conf->r10bio_pool = mempool_create(NR_RAID10_BIOS, r10bio_pool_alloc,
r10bio_pool_free, conf);
if (!conf->r10bio_pool) {
printk(KERN_ERR "raid10: couldn't allocate memory for %s\n",
mdname(mddev));
goto out_free_conf;
}
conf->mddev = mddev;
spin_lock_init(&conf->device_lock); spin_lock_init(&conf->device_lock);
INIT_LIST_HEAD(&conf->retry_list);
spin_lock_init(&conf->resync_lock);
init_waitqueue_head(&conf->wait_barrier);
conf->thread = md_register_thread(raid10d, mddev, NULL);
if (!conf->thread)
goto out;
conf->scale_disks = 0;
conf->mddev = mddev;
return conf;
out:
printk(KERN_ERR "md/raid10:%s: couldn't allocate memory.\n",
mdname(mddev));
if (conf) {
if (conf->r10bio_pool)
mempool_destroy(conf->r10bio_pool);
kfree(conf->mirrors);
safe_put_page(conf->tmppage);
kfree(conf);
}
return ERR_PTR(err);
}
static int run(mddev_t *mddev)
{
conf_t *conf;
int i, disk_idx, chunk_size;
mirror_info_t *disk;
mdk_rdev_t *rdev;
sector_t size;
/*
* copy the already verified devices into our private RAID10
* bookkeeping area. [whatever we allocate in run(),
* should be freed in stop()]
*/
if (mddev->private == NULL) {
conf = setup_conf(mddev);
if (IS_ERR(conf))
return PTR_ERR(conf);
mddev->private = conf;
}
conf = mddev->private;
if (!conf)
goto out;
mddev->queue->queue_lock = &conf->device_lock; mddev->queue->queue_lock = &conf->device_lock;
mddev->thread = conf->thread;
conf->thread = NULL;
chunk_size = mddev->chunk_sectors << 9; chunk_size = mddev->chunk_sectors << 9;
blk_queue_io_min(mddev->queue, chunk_size); blk_queue_io_min(mddev->queue, chunk_size);
if (conf->raid_disks % conf->near_copies) if (conf->raid_disks % conf->near_copies)
...@@ -2251,9 +2297,14 @@ static int run(mddev_t *mddev) ...@@ -2251,9 +2297,14 @@ static int run(mddev_t *mddev)
list_for_each_entry(rdev, &mddev->disks, same_set) { list_for_each_entry(rdev, &mddev->disks, same_set) {
disk_idx = rdev->raid_disk; disk_idx = rdev->raid_disk;
if (disk_idx >= mddev->raid_disks if (disk_idx >= conf->raid_disks
|| disk_idx < 0) || disk_idx < 0)
continue; continue;
if (conf->scale_disks) {
disk_idx *= conf->scale_disks;
rdev->raid_disk = disk_idx;
/* MOVE 'rd%d' link !! */
}
disk = conf->mirrors + disk_idx; disk = conf->mirrors + disk_idx;
disk->rdev = rdev; disk->rdev = rdev;
...@@ -2271,14 +2322,9 @@ static int run(mddev_t *mddev) ...@@ -2271,14 +2322,9 @@ static int run(mddev_t *mddev)
disk->head_position = 0; disk->head_position = 0;
} }
INIT_LIST_HEAD(&conf->retry_list);
spin_lock_init(&conf->resync_lock);
init_waitqueue_head(&conf->wait_barrier);
/* need to check that every block has at least one working mirror */ /* need to check that every block has at least one working mirror */
if (!enough(conf)) { if (!enough(conf)) {
printk(KERN_ERR "raid10: not enough operational mirrors for %s\n", printk(KERN_ERR "md/raid10:%s: not enough operational mirrors.\n",
mdname(mddev)); mdname(mddev));
goto out_free_conf; goto out_free_conf;
} }
...@@ -2297,28 +2343,21 @@ static int run(mddev_t *mddev) ...@@ -2297,28 +2343,21 @@ static int run(mddev_t *mddev)
} }
} }
mddev->thread = md_register_thread(raid10d, mddev, NULL);
if (!mddev->thread) {
printk(KERN_ERR
"raid10: couldn't allocate thread for %s\n",
mdname(mddev));
goto out_free_conf;
}
if (mddev->recovery_cp != MaxSector) if (mddev->recovery_cp != MaxSector)
printk(KERN_NOTICE "raid10: %s is not clean" printk(KERN_NOTICE "md/raid10:%s: not clean"
" -- starting background reconstruction\n", " -- starting background reconstruction\n",
mdname(mddev)); mdname(mddev));
printk(KERN_INFO printk(KERN_INFO
"raid10: raid set %s active with %d out of %d devices\n", "md/raid10:%s: active with %d out of %d devices\n",
mdname(mddev), mddev->raid_disks - mddev->degraded, mdname(mddev), conf->raid_disks - mddev->degraded,
mddev->raid_disks); conf->raid_disks);
/* /*
* Ok, everything is just fine now * Ok, everything is just fine now
*/ */
md_set_array_sectors(mddev, raid10_size(mddev, 0, 0)); mddev->dev_sectors = conf->dev_sectors;
mddev->resync_max_sectors = raid10_size(mddev, 0, 0); size = raid10_size(mddev, 0, 0);
md_set_array_sectors(mddev, size);
mddev->resync_max_sectors = size;
mddev->queue->unplug_fn = raid10_unplug; mddev->queue->unplug_fn = raid10_unplug;
mddev->queue->backing_dev_info.congested_fn = raid10_congested; mddev->queue->backing_dev_info.congested_fn = raid10_congested;
...@@ -2336,7 +2375,7 @@ static int run(mddev_t *mddev) ...@@ -2336,7 +2375,7 @@ static int run(mddev_t *mddev)
mddev->queue->backing_dev_info.ra_pages = 2* stripe; mddev->queue->backing_dev_info.ra_pages = 2* stripe;
} }
if (conf->near_copies < mddev->raid_disks) if (conf->near_copies < conf->raid_disks)
blk_queue_merge_bvec(mddev->queue, raid10_mergeable_bvec); blk_queue_merge_bvec(mddev->queue, raid10_mergeable_bvec);
md_integrity_register(mddev); md_integrity_register(mddev);
return 0; return 0;
...@@ -2348,6 +2387,7 @@ static int run(mddev_t *mddev) ...@@ -2348,6 +2387,7 @@ static int run(mddev_t *mddev)
kfree(conf->mirrors); kfree(conf->mirrors);
kfree(conf); kfree(conf);
mddev->private = NULL; mddev->private = NULL;
md_unregister_thread(mddev->thread);
out: out:
return -EIO; return -EIO;
} }
...@@ -2384,6 +2424,61 @@ static void raid10_quiesce(mddev_t *mddev, int state) ...@@ -2384,6 +2424,61 @@ static void raid10_quiesce(mddev_t *mddev, int state)
} }
} }
static void *raid10_takeover_raid0(mddev_t *mddev)
{
mdk_rdev_t *rdev;
conf_t *conf;
if (mddev->degraded > 0) {
printk(KERN_ERR "md/raid10:%s: Error: degraded raid0!\n",
mdname(mddev));
return ERR_PTR(-EINVAL);
}
/* Update slot numbers to obtain
* degraded raid10 with missing mirrors
*/
list_for_each_entry(rdev, &mddev->disks, same_set) {
rdev->raid_disk *= 2;
}
/* Set new parameters */
mddev->new_level = 10;
/* new layout: far_copies = 1, near_copies = 2 */
mddev->new_layout = (1<<8) + 2;
mddev->new_chunk_sectors = mddev->chunk_sectors;
mddev->delta_disks = mddev->raid_disks;
mddev->degraded = mddev->raid_disks;
mddev->raid_disks *= 2;
/* make sure it will be not marked as dirty */
mddev->recovery_cp = MaxSector;
conf = setup_conf(mddev);
conf->scale_disks = 2;
return conf;
}
static void *raid10_takeover(mddev_t *mddev)
{
struct raid0_private_data *raid0_priv;
/* raid10 can take over:
* raid0 - providing it has only two drives
*/
if (mddev->level == 0) {
/* for raid0 takeover only one zone is supported */
raid0_priv = mddev->private;
if (raid0_priv->nr_strip_zones > 1) {
printk(KERN_ERR "md/raid10:%s: cannot takeover raid 0"
" with more than one zone.\n",
mdname(mddev));
return ERR_PTR(-EINVAL);
}
return raid10_takeover_raid0(mddev);
}
return ERR_PTR(-EINVAL);
}
static struct mdk_personality raid10_personality = static struct mdk_personality raid10_personality =
{ {
.name = "raid10", .name = "raid10",
...@@ -2400,6 +2495,7 @@ static struct mdk_personality raid10_personality = ...@@ -2400,6 +2495,7 @@ static struct mdk_personality raid10_personality =
.sync_request = sync_request, .sync_request = sync_request,
.quiesce = raid10_quiesce, .quiesce = raid10_quiesce,
.size = raid10_size, .size = raid10_size,
.takeover = raid10_takeover,
}; };
static int __init raid_init(void) static int __init raid_init(void)
......
...@@ -33,9 +33,16 @@ struct r10_private_data_s { ...@@ -33,9 +33,16 @@ struct r10_private_data_s {
* 1 stripe. * 1 stripe.
*/ */
sector_t dev_sectors; /* temp copy of mddev->dev_sectors */
int chunk_shift; /* shift from chunks to sectors */ int chunk_shift; /* shift from chunks to sectors */
sector_t chunk_mask; sector_t chunk_mask;
int scale_disks; /* When starting array, multiply
* each ->raid_disk by this.
* Need for raid0->raid10 migration
*/
struct list_head retry_list; struct list_head retry_list;
/* queue pending writes and submit them on unplug */ /* queue pending writes and submit them on unplug */
struct bio_list pending_bio_list; struct bio_list pending_bio_list;
...@@ -57,6 +64,11 @@ struct r10_private_data_s { ...@@ -57,6 +64,11 @@ struct r10_private_data_s {
mempool_t *r10bio_pool; mempool_t *r10bio_pool;
mempool_t *r10buf_pool; mempool_t *r10buf_pool;
struct page *tmppage; struct page *tmppage;
/* When taking over an array from a different personality, we store
* the new thread here until we fully activate the array.
*/
struct mdk_thread_s *thread;
}; };
typedef struct r10_private_data_s conf_t; typedef struct r10_private_data_s conf_t;
......
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册