Skip to content

Commit

Permalink
Merge branch 'for-linus' of git://neil.brown.name/md
Browse files Browse the repository at this point in the history
* '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
  ...
  • Loading branch information
Linus Torvalds committed May 21, 2010
2 parents d79df0b + 19fdb9e commit 6e45139
Show file tree
Hide file tree
Showing 14 changed files with 987 additions and 582 deletions.
4 changes: 2 additions & 2 deletions drivers/md/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -100,8 +100,8 @@ config MD_RAID1
If unsure, say Y.

config MD_RAID10
tristate "RAID-10 (mirrored striping) mode (EXPERIMENTAL)"
depends on BLK_DEV_MD && EXPERIMENTAL
tristate "RAID-10 (mirrored striping) mode"
depends on BLK_DEV_MD
---help---
RAID-10 provides a combination of striping (RAID-0) and
mirroring (RAID-1) with easier configuration and more flexible
Expand Down
41 changes: 35 additions & 6 deletions drivers/md/bitmap.c
Original file line number Diff line number Diff line change
Expand Up @@ -505,7 +505,7 @@ void bitmap_update_sb(struct bitmap *bitmap)
return;
}
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);
if (bitmap->mddev->events < bitmap->events_cleared) {
/* rocking back to read-only */
Expand All @@ -526,7 +526,7 @@ void bitmap_print_sb(struct bitmap *bitmap)

if (!bitmap || !bitmap->sb_page)
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 " magic: %08x\n", le32_to_cpu(sb->magic));
printk(KERN_DEBUG " version: %d\n", le32_to_cpu(sb->version));
Expand Down Expand Up @@ -575,7 +575,7 @@ static int bitmap_read_sb(struct bitmap *bitmap)
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);
daemon_sleep = le32_to_cpu(sb->daemon_sleep) * HZ;
Expand Down Expand Up @@ -661,7 +661,7 @@ static int bitmap_mask_state(struct bitmap *bitmap, enum bitmap_state bits,
return 0;
}
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;
switch (op) {
case MASK_SET: sb->state |= cpu_to_le32(bits);
Expand Down Expand Up @@ -1292,9 +1292,14 @@ int bitmap_startwrite(struct bitmap *bitmap, sector_t offset, unsigned long sect
if (!bitmap) return 0;

if (behind) {
int bw;
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",
atomic_read(&bitmap->behind_writes), bitmap->max_write_behind);
bw, bitmap->max_write_behind);
}

while (sectors) {
Expand Down Expand Up @@ -1351,7 +1356,8 @@ void bitmap_endwrite(struct bitmap *bitmap, sector_t offset, unsigned long secto
{
if (!bitmap) return;
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",
atomic_read(&bitmap->behind_writes), bitmap->max_write_behind);
}
Expand Down Expand Up @@ -1675,6 +1681,7 @@ int bitmap_create(mddev_t *mddev)
atomic_set(&bitmap->pending_writes, 0);
init_waitqueue_head(&bitmap->write_wait);
init_waitqueue_head(&bitmap->overflow_wait);
init_waitqueue_head(&bitmap->behind_wait);

bitmap->mddev = mddev;

Expand Down Expand Up @@ -2006,13 +2013,35 @@ static ssize_t can_clear_store(mddev_t *mddev, const char *buf, size_t len)
static struct md_sysfs_entry bitmap_can_clear =
__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[] = {
&bitmap_location.attr,
&bitmap_timeout.attr,
&bitmap_backlog.attr,
&bitmap_chunksize.attr,
&bitmap_metadata.attr,
&bitmap_can_clear.attr,
&max_backlog_used.attr,
NULL
};
struct attribute_group md_bitmap_group = {
Expand Down
2 changes: 2 additions & 0 deletions drivers/md/bitmap.h
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,7 @@ struct bitmap {
int allclean;

atomic_t behind_writes;
unsigned long behind_writes_used; /* highest actual value at runtime */

/*
* the bitmap daemon - periodically wakes up and sweeps the bitmap
Expand All @@ -239,6 +240,7 @@ struct bitmap {
atomic_t pending_writes; /* pending writes to the bitmap file */
wait_queue_head_t write_wait;
wait_queue_head_t overflow_wait;
wait_queue_head_t behind_wait;

struct sysfs_dirent *sysfs_can_clear;
};
Expand Down
9 changes: 4 additions & 5 deletions drivers/md/faulty.c
Original file line number Diff line number Diff line change
Expand Up @@ -169,10 +169,9 @@ static void add_sector(conf_t *conf, sector_t start, int mode)
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 = (conf_t*)mddev->private;
conf_t *conf = mddev->private;
int failit = 0;

if (bio_data_dir(bio) == WRITE) {
Expand Down Expand Up @@ -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)
{
conf_t *conf = (conf_t*)mddev->private;
conf_t *conf = mddev->private;
int n;

if ((n=atomic_read(&conf->counters[WriteTransient])) != 0)
Expand Down Expand Up @@ -328,7 +327,7 @@ static int run(mddev_t *mddev)

static int stop(mddev_t *mddev)
{
conf_t *conf = (conf_t *)mddev->private;
conf_t *conf = mddev->private;

kfree(conf);
mddev->private = NULL;
Expand Down
36 changes: 16 additions & 20 deletions drivers/md/linear.c
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,8 @@ static linear_conf_t *linear_conf(mddev_t *mddev, int raid_disks)
sector_t sectors;

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;
}

Expand Down Expand Up @@ -187,7 +188,8 @@ static linear_conf_t *linear_conf(mddev_t *mddev, int 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;
}

Expand Down Expand Up @@ -282,29 +284,21 @@ static int linear_stop (mddev_t *mddev)
rcu_barrier();
blk_sync_queue(mddev->queue); /* the unplug fn references 'conf'*/
kfree(conf);
mddev->private = NULL;

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;
sector_t start_sector;
int cpu;

if (unlikely(bio_rw_flagged(bio, BIO_RW_BARRIER))) {
md_barrier_request(mddev, bio);
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();
tmp_dev = which_dev(mddev, bio->bi_sector);
start_sector = tmp_dev->end_sector - tmp_dev->rdev->sectors;
Expand All @@ -314,12 +308,14 @@ static int linear_make_request (struct request_queue *q, struct bio *bio)
|| (bio->bi_sector < start_sector))) {
char b[BDEVNAME_SIZE];

printk("linear_make_request: Sector %llu out of bounds on "
"dev %s: %llu sectors, offset %llu\n",
(unsigned long long)bio->bi_sector,
bdevname(tmp_dev->rdev->bdev, b),
(unsigned long long)tmp_dev->rdev->sectors,
(unsigned long long)start_sector);
printk(KERN_ERR
"md/linear:%s: make_request: Sector %llu out of bounds on "
"dev %s: %llu sectors, offset %llu\n",
mdname(mddev),
(unsigned long long)bio->bi_sector,
bdevname(tmp_dev->rdev->bdev, b),
(unsigned long long)tmp_dev->rdev->sectors,
(unsigned long long)start_sector);
rcu_read_unlock();
bio_io_error(bio);
return 0;
Expand All @@ -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);

if (linear_make_request(q, &bp->bio1))
if (linear_make_request(mddev, &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);
bio_pair_release(bp);
return 0;
Expand Down
Loading

0 comments on commit 6e45139

Please sign in to comment.