* [PATCH md 001 of 7] Remove old cruft from md_k.h header file.
2005-08-29 7:33 [PATCH md 000 of 7] Introduction NeilBrown
@ 2005-08-29 7:33 ` NeilBrown
2005-08-29 7:33 ` [PATCH md 007 of 7] Tidy up daemon stop/start code in md/bitmap.c NeilBrown
` (5 subsequent siblings)
6 siblings, 0 replies; 12+ messages in thread
From: NeilBrown @ 2005-08-29 7:33 UTC (permalink / raw)
To: Andrew Morton; +Cc: linux-raid
These inlines haven't been used for ages, they should go.
Signed-off-by: Neil Brown <neilb@cse.unsw.edu.au>
### Diffstat output
./include/linux/raid/md_k.h | 64 --------------------------------------------
1 file changed, 64 deletions(-)
diff ./include/linux/raid/md_k.h~current~ ./include/linux/raid/md_k.h
--- ./include/linux/raid/md_k.h~current~ 2005-08-29 15:52:25.000000000 +1000
+++ ./include/linux/raid/md_k.h 2005-08-29 15:52:38.000000000 +1000
@@ -86,70 +86,6 @@ typedef struct mdk_rdev_s mdk_rdev_t;
#define MAX_CHUNK_SIZE (4096*1024)
/*
- * default readahead
- */
-
-static inline int disk_faulty(mdp_disk_t * d)
-{
- return d->state & (1 << MD_DISK_FAULTY);
-}
-
-static inline int disk_active(mdp_disk_t * d)
-{
- return d->state & (1 << MD_DISK_ACTIVE);
-}
-
-static inline int disk_sync(mdp_disk_t * d)
-{
- return d->state & (1 << MD_DISK_SYNC);
-}
-
-static inline int disk_spare(mdp_disk_t * d)
-{
- return !disk_sync(d) && !disk_active(d) && !disk_faulty(d);
-}
-
-static inline int disk_removed(mdp_disk_t * d)
-{
- return d->state & (1 << MD_DISK_REMOVED);
-}
-
-static inline void mark_disk_faulty(mdp_disk_t * d)
-{
- d->state |= (1 << MD_DISK_FAULTY);
-}
-
-static inline void mark_disk_active(mdp_disk_t * d)
-{
- d->state |= (1 << MD_DISK_ACTIVE);
-}
-
-static inline void mark_disk_sync(mdp_disk_t * d)
-{
- d->state |= (1 << MD_DISK_SYNC);
-}
-
-static inline void mark_disk_spare(mdp_disk_t * d)
-{
- d->state = 0;
-}
-
-static inline void mark_disk_removed(mdp_disk_t * d)
-{
- d->state = (1 << MD_DISK_FAULTY) | (1 << MD_DISK_REMOVED);
-}
-
-static inline void mark_disk_inactive(mdp_disk_t * d)
-{
- d->state &= ~(1 << MD_DISK_ACTIVE);
-}
-
-static inline void mark_disk_nonsync(mdp_disk_t * d)
-{
- d->state &= ~(1 << MD_DISK_SYNC);
-}
-
-/*
* MD's 'extended' device
*/
struct mdk_rdev_s
^ permalink raw reply [flat|nested] 12+ messages in thread* [PATCH md 007 of 7] Tidy up daemon stop/start code in md/bitmap.c
2005-08-29 7:33 [PATCH md 000 of 7] Introduction NeilBrown
2005-08-29 7:33 ` [PATCH md 001 of 7] Remove old cruft from md_k.h header file NeilBrown
@ 2005-08-29 7:33 ` NeilBrown
2005-08-29 7:33 ` [PATCH md 006 of 7] Ensure bitmap_writeback_daemon handles shutdown properly NeilBrown
` (4 subsequent siblings)
6 siblings, 0 replies; 12+ messages in thread
From: NeilBrown @ 2005-08-29 7:33 UTC (permalink / raw)
To: Andrew Morton; +Cc: linux-raid
The bitmap code used to have two daemons, so there is some 'common'
start/stop code. But now there is only one, so the common code is
just noise.
This patch tidies this up somewhat.
Signed-off-by: Neil Brown <neilb@cse.unsw.edu.au>
### Diffstat output
./drivers/md/bitmap.c | 73 ++++++++++++++++++--------------------------------
1 file changed, 27 insertions(+), 46 deletions(-)
diff ./drivers/md/bitmap.c~current~ ./drivers/md/bitmap.c
--- ./drivers/md/bitmap.c~current~ 2005-08-29 16:46:50.000000000 +1000
+++ ./drivers/md/bitmap.c 2005-08-29 17:04:24.000000000 +1000
@@ -626,7 +626,7 @@ static void bitmap_file_unmap(struct bit
page_cache_release(sb_page);
}
-static void bitmap_stop_daemons(struct bitmap *bitmap);
+static void bitmap_stop_daemon(struct bitmap *bitmap);
/* dequeue the next item in a page list -- don't call from irq context */
static struct page_list *dequeue_page(struct bitmap *bitmap)
@@ -668,7 +668,7 @@ static void bitmap_file_put(struct bitma
bitmap->file = NULL;
spin_unlock_irqrestore(&bitmap->lock, flags);
- bitmap_stop_daemons(bitmap);
+ bitmap_stop_daemon(bitmap);
drain_write_queues(bitmap);
@@ -1188,21 +1188,12 @@ static void bitmap_writeback_daemon(mdde
}
}
-static int bitmap_start_daemon(struct bitmap *bitmap, mdk_thread_t **ptr,
+static mdk_thread_t *bitmap_start_daemon(struct bitmap *bitmap,
void (*func)(mddev_t *), char *name)
{
mdk_thread_t *daemon;
- unsigned long flags;
char namebuf[32];
- spin_lock_irqsave(&bitmap->lock, flags);
- *ptr = NULL;
-
- if (!bitmap->file) /* no need for daemon if there's no backing file */
- goto out_unlock;
-
- spin_unlock_irqrestore(&bitmap->lock, flags);
-
#ifdef INJECT_FATAL_FAULT_2
daemon = NULL;
#else
@@ -1212,47 +1203,32 @@ static int bitmap_start_daemon(struct bi
if (!daemon) {
printk(KERN_ERR "%s: failed to start bitmap daemon\n",
bmname(bitmap));
- return -ECHILD;
+ return ERR_PTR(-ECHILD);
}
- spin_lock_irqsave(&bitmap->lock, flags);
- *ptr = daemon;
-
md_wakeup_thread(daemon); /* start it running */
PRINTK("%s: %s daemon (pid %d) started...\n",
bmname(bitmap), name, daemon->tsk->pid);
-out_unlock:
- spin_unlock_irqrestore(&bitmap->lock, flags);
- return 0;
-}
-static int bitmap_start_daemons(struct bitmap *bitmap)
-{
- int err = bitmap_start_daemon(bitmap, &bitmap->writeback_daemon,
- bitmap_writeback_daemon, "bitmap_wb");
- return err;
+ return daemon;
}
-static void bitmap_stop_daemon(struct bitmap *bitmap, mdk_thread_t **ptr)
+static void bitmap_stop_daemon(struct bitmap *bitmap)
{
- mdk_thread_t *daemon;
- unsigned long flags;
-
- spin_lock_irqsave(&bitmap->lock, flags);
- daemon = *ptr;
- *ptr = NULL;
- spin_unlock_irqrestore(&bitmap->lock, flags);
- if (daemon)
- md_unregister_thread(daemon); /* destroy the thread */
-}
+ /* the daemon can't stop itself... it'll just exit instead... */
+ if (bitmap->writeback_daemon && ! IS_ERR(bitmap->writeback_daemon) &&
+ current->pid != bitmap->writeback_daemon->tsk->pid) {
+ mdk_thread_t *daemon;
+ unsigned long flags;
-static void bitmap_stop_daemons(struct bitmap *bitmap)
-{
- /* the daemons can't stop themselves... they'll just exit instead... */
- if (bitmap->writeback_daemon &&
- current->pid != bitmap->writeback_daemon->tsk->pid)
- bitmap_stop_daemon(bitmap, &bitmap->writeback_daemon);
+ spin_lock_irqsave(&bitmap->lock, flags);
+ daemon = bitmap->writeback_daemon;
+ bitmap->writeback_daemon = NULL;
+ spin_unlock_irqrestore(&bitmap->lock, flags);
+ if (daemon && ! IS_ERR(daemon))
+ md_unregister_thread(daemon); /* destroy the thread */
+ }
}
static bitmap_counter_t *bitmap_get_counter(struct bitmap *bitmap,
@@ -1637,10 +1613,15 @@ int bitmap_create(mddev_t *mddev)
mddev->bitmap = bitmap;
- /* kick off the bitmap daemons */
- err = bitmap_start_daemons(bitmap);
- if (err)
- return err;
+ if (file)
+ /* kick off the bitmap writeback daemon */
+ bitmap->writeback_daemon =
+ bitmap_start_daemon(bitmap,
+ bitmap_writeback_daemon,
+ "bitmap_wb");
+
+ if (IS_ERR(bitmap->writeback_daemon))
+ return PTR_ERR(bitmap->writeback_daemon);
return bitmap_update_sb(bitmap);
error:
^ permalink raw reply [flat|nested] 12+ messages in thread* [PATCH md 006 of 7] Ensure bitmap_writeback_daemon handles shutdown properly.
2005-08-29 7:33 [PATCH md 000 of 7] Introduction NeilBrown
2005-08-29 7:33 ` [PATCH md 001 of 7] Remove old cruft from md_k.h header file NeilBrown
2005-08-29 7:33 ` [PATCH md 007 of 7] Tidy up daemon stop/start code in md/bitmap.c NeilBrown
@ 2005-08-29 7:33 ` NeilBrown
2005-08-29 7:33 ` [PATCH md 004 of 7] write-intent bitmap support for raid6 NeilBrown
` (3 subsequent siblings)
6 siblings, 0 replies; 12+ messages in thread
From: NeilBrown @ 2005-08-29 7:33 UTC (permalink / raw)
To: Andrew Morton; +Cc: linux-raid
mddev->bitmap gets clearred before the writeback daemon is stopped.
So the write_back daemon needs to be careful not to dereference
the 'bitmap' if it is NULL.
Signed-off-by: Neil Brown <neilb@cse.unsw.edu.au>
### Diffstat output
./drivers/md/bitmap.c | 3 +++
1 file changed, 3 insertions(+)
diff ./drivers/md/bitmap.c~current~ ./drivers/md/bitmap.c
--- ./drivers/md/bitmap.c~current~ 2005-08-29 16:32:20.000000000 +1000
+++ ./drivers/md/bitmap.c 2005-08-29 16:46:50.000000000 +1000
@@ -1156,6 +1156,9 @@ static void bitmap_writeback_daemon(mdde
err = -EINTR;
goto out;
}
+ if (bitmap == NULL)
+ /* about to be stopped. */
+ return;
PRINTK("%s: bitmap writeback daemon woke up...\n", bmname(bitmap));
/* wait on bitmap page writebacks */
^ permalink raw reply [flat|nested] 12+ messages in thread* [PATCH md 004 of 7] write-intent bitmap support for raid6
2005-08-29 7:33 [PATCH md 000 of 7] Introduction NeilBrown
` (2 preceding siblings ...)
2005-08-29 7:33 ` [PATCH md 006 of 7] Ensure bitmap_writeback_daemon handles shutdown properly NeilBrown
@ 2005-08-29 7:33 ` NeilBrown
2005-08-29 7:33 ` [PATCH md 003 of 7] Add write-intent-bitmap support to raid5 NeilBrown
` (2 subsequent siblings)
6 siblings, 0 replies; 12+ messages in thread
From: NeilBrown @ 2005-08-29 7:33 UTC (permalink / raw)
To: Andrew Morton; +Cc: linux-raid
This is a direct port of the raid5 patch.
Signed-off-by: Neil Brown <neilb@cse.unsw.edu.au>
### Diffstat output
./drivers/md/md.c | 2
./drivers/md/raid6main.c | 133 +++++++++++++++++++++++++++++++++++++++++++----
2 files changed, 124 insertions(+), 11 deletions(-)
diff ./drivers/md/md.c~current~ ./drivers/md/md.c
--- ./drivers/md/md.c~current~ 2005-08-29 16:32:24.000000000 +1000
+++ ./drivers/md/md.c 2005-08-29 16:37:35.000000000 +1000
@@ -645,7 +645,7 @@ static int super_90_validate(mddev_t *md
if (sb->state & (1<<MD_SB_BITMAP_PRESENT) &&
mddev->bitmap_file == NULL) {
- if (mddev->level != 1 && mddev->level != 5) {
+ if (mddev->level != 1 && mddev->level != 5 && mddev->level != 6) {
/* FIXME use a better test */
printk(KERN_WARNING "md: bitmaps only support for raid1\n");
return -EINVAL;
diff ./drivers/md/raid6main.c~current~ ./drivers/md/raid6main.c
--- ./drivers/md/raid6main.c~current~ 2005-08-29 16:32:20.000000000 +1000
+++ ./drivers/md/raid6main.c 2005-08-29 16:37:35.000000000 +1000
@@ -29,6 +29,8 @@
#include <asm/atomic.h>
#include "raid6.h"
+#include <linux/raid/bitmap.h>
+
/*
* Stripe cache
*/
@@ -98,8 +100,13 @@ static inline void __release_stripe(raid
if (test_bit(STRIPE_HANDLE, &sh->state)) {
if (test_bit(STRIPE_DELAYED, &sh->state))
list_add_tail(&sh->lru, &conf->delayed_list);
- else
+ else if (test_bit(STRIPE_BIT_DELAY, &sh->state) &&
+ conf->seq_write == sh->bm_seq)
+ list_add_tail(&sh->lru, &conf->bitmap_list);
+ else {
+ clear_bit(STRIPE_BIT_DELAY, &sh->state);
list_add_tail(&sh->lru, &conf->handle_list);
+ }
md_wakeup_thread(conf->mddev->thread);
} else {
if (test_and_clear_bit(STRIPE_PREREAD_ACTIVE, &sh->state)) {
@@ -262,6 +269,9 @@ static struct stripe_head *get_active_st
spin_lock_irq(&conf->device_lock);
do {
+ wait_event_lock_irq(conf->wait_for_stripe,
+ conf->quiesce == 0,
+ conf->device_lock, /* nothing */);
sh = __find_stripe(conf, sector);
if (!sh) {
if (!conf->inactive_blocked)
@@ -906,6 +916,7 @@ static int add_stripe_bio(struct stripe_
{
struct bio **bip;
raid6_conf_t *conf = sh->raid_conf;
+ int firstwrite=0;
PRINTK("adding bh b#%llu to stripe s#%llu\n",
(unsigned long long)bi->bi_sector,
@@ -914,9 +925,11 @@ static int add_stripe_bio(struct stripe_
spin_lock(&sh->lock);
spin_lock_irq(&conf->device_lock);
- if (forwrite)
+ if (forwrite) {
bip = &sh->dev[dd_idx].towrite;
- else
+ if (*bip == NULL && sh->dev[dd_idx].written == NULL)
+ firstwrite = 1;
+ } else
bip = &sh->dev[dd_idx].toread;
while (*bip && (*bip)->bi_sector < bi->bi_sector) {
if ((*bip)->bi_sector + ((*bip)->bi_size >> 9) > bi->bi_sector)
@@ -939,6 +952,13 @@ static int add_stripe_bio(struct stripe_
(unsigned long long)bi->bi_sector,
(unsigned long long)sh->sector, dd_idx);
+ if (conf->mddev->bitmap && firstwrite) {
+ sh->bm_seq = conf->seq_write;
+ bitmap_startwrite(conf->mddev->bitmap, sh->sector,
+ STRIPE_SECTORS, 0);
+ set_bit(STRIPE_BIT_DELAY, &sh->state);
+ }
+
if (forwrite) {
/* check if page is covered */
sector_t sector = sh->dev[dd_idx].sector;
@@ -1066,12 +1086,13 @@ static void handle_stripe(struct stripe_
* need to be failed
*/
if (failed > 2 && to_read+to_write+written) {
- spin_lock_irq(&conf->device_lock);
for (i=disks; i--; ) {
+ int bitmap_end = 0;
+ spin_lock_irq(&conf->device_lock);
/* fail all writes first */
bi = sh->dev[i].towrite;
sh->dev[i].towrite = NULL;
- if (bi) to_write--;
+ if (bi) { to_write--; bitmap_end = 1; }
if (test_and_clear_bit(R5_Overlap, &sh->dev[i].flags))
wake_up(&conf->wait_for_overlap);
@@ -1089,6 +1110,7 @@ static void handle_stripe(struct stripe_
/* and fail all 'written' */
bi = sh->dev[i].written;
sh->dev[i].written = NULL;
+ if (bi) bitmap_end = 1;
while (bi && bi->bi_sector < sh->dev[i].sector + STRIPE_SECTORS) {
struct bio *bi2 = r5_next_bio(bi, sh->dev[i].sector);
clear_bit(BIO_UPTODATE, &bi->bi_flags);
@@ -1117,8 +1139,11 @@ static void handle_stripe(struct stripe_
bi = nextbi;
}
}
+ spin_unlock_irq(&conf->device_lock);
+ if (bitmap_end)
+ bitmap_endwrite(conf->mddev->bitmap, sh->sector,
+ STRIPE_SECTORS, 0, 0);
}
- spin_unlock_irq(&conf->device_lock);
}
if (failed > 2 && syncing) {
md_done_sync(conf->mddev, STRIPE_SECTORS,0);
@@ -1155,6 +1180,7 @@ static void handle_stripe(struct stripe_
if (!test_bit(R5_LOCKED, &dev->flags) &&
test_bit(R5_UPTODATE, &dev->flags) ) {
/* We can return any write requests */
+ int bitmap_end = 0;
struct bio *wbi, *wbi2;
PRINTK("Return write for stripe %llu disc %d\n",
(unsigned long long)sh->sector, i);
@@ -1170,7 +1196,13 @@ static void handle_stripe(struct stripe_
}
wbi = wbi2;
}
+ if (dev->towrite == NULL)
+ bitmap_end = 1;
spin_unlock_irq(&conf->device_lock);
+ if (bitmap_end)
+ bitmap_endwrite(conf->mddev->bitmap, sh->sector,
+ STRIPE_SECTORS,
+ !test_bit(STRIPE_DEGRADED, &sh->state), 0);
}
}
}
@@ -1285,7 +1317,8 @@ static void handle_stripe(struct stripe_
}
}
/* now if nothing is locked, and if we have enough data, we can start a write request */
- if (locked == 0 && rcw == 0) {
+ if (locked == 0 && rcw == 0 &&
+ !test_bit(STRIPE_BIT_DELAY, &sh->state)) {
if ( must_compute > 0 ) {
/* We have failed blocks and need to compute them */
switch ( failed ) {
@@ -1388,6 +1421,7 @@ static void handle_stripe(struct stripe_
bdev = &sh->dev[failed_num[1]];
locked += !test_bit(R5_LOCKED, &bdev->flags);
set_bit(R5_LOCKED, &bdev->flags);
+ clear_bit(STRIPE_DEGRADED, &sh->state);
set_bit(R5_Wantwrite, &bdev->flags);
set_bit(STRIPE_INSYNC, &sh->state);
@@ -1457,6 +1491,8 @@ static void handle_stripe(struct stripe_
bi->bi_next = NULL;
generic_make_request(bi);
} else {
+ if (rw == 1)
+ set_bit(STRIPE_DEGRADED, &sh->state);
PRINTK("skip op %ld on disc %d for sector %llu\n",
bi->bi_rw, i, (unsigned long long)sh->sector);
clear_bit(R5_LOCKED, &sh->dev[i].flags);
@@ -1481,6 +1517,20 @@ static inline void raid6_activate_delaye
}
}
+static inline void activate_bit_delay(raid6_conf_t *conf)
+{
+ /* device_lock is held */
+ struct list_head head;
+ list_add(&head, &conf->bitmap_list);
+ list_del_init(&conf->bitmap_list);
+ while (!list_empty(&head)) {
+ struct stripe_head *sh = list_entry(head.next, struct stripe_head, lru);
+ list_del_init(&sh->lru);
+ atomic_inc(&sh->count);
+ __release_stripe(conf, sh);
+ }
+}
+
static void unplug_slaves(mddev_t *mddev)
{
raid6_conf_t *conf = mddev_to_conf(mddev);
@@ -1513,8 +1563,10 @@ static void raid6_unplug_device(request_
spin_lock_irqsave(&conf->device_lock, flags);
- if (blk_remove_plug(q))
+ if (blk_remove_plug(q)) {
+ conf->seq_flush++;
raid6_activate_delayed(conf);
+ }
md_wakeup_thread(mddev->thread);
spin_unlock_irqrestore(&conf->device_lock, flags);
@@ -1652,10 +1704,20 @@ static sector_t sync_request(mddev_t *md
sector_t first_sector;
int raid_disks = conf->raid_disks;
int data_disks = raid_disks - 2;
+ sector_t max_sector = mddev->size << 1;
+ int sync_blocks;
- if (sector_nr >= mddev->size <<1) {
+ if (sector_nr >= max_sector) {
/* just being told to finish up .. nothing much to do */
unplug_slaves(mddev);
+
+ if (mddev->curr_resync < max_sector) /* aborted */
+ bitmap_end_sync(mddev->bitmap, mddev->curr_resync,
+ &sync_blocks, 1);
+ else /* compelted sync */
+ conf->fullsync = 0;
+ bitmap_close_sync(mddev->bitmap);
+
return 0;
}
/* if there are 2 or more failed drives and we are trying
@@ -1667,6 +1729,13 @@ static sector_t sync_request(mddev_t *md
*skipped = 1;
return rv;
}
+ if (!bitmap_start_sync(mddev->bitmap, sector_nr, &sync_blocks, 1) &&
+ !conf->fullsync && sync_blocks >= STRIPE_SECTORS) {
+ /* we can skip this block, and probably more */
+ sync_blocks /= STRIPE_SECTORS;
+ *skipped = 1;
+ return sync_blocks * STRIPE_SECTORS; /* keep things rounded to whole stripes */
+ }
x = sector_nr;
chunk_offset = sector_div(x, sectors_per_chunk);
@@ -1683,6 +1752,7 @@ static sector_t sync_request(mddev_t *md
*/
schedule_timeout_uninterruptible(1);
}
+ bitmap_start_sync(mddev->bitmap, sector_nr, &sync_blocks, 0);
spin_lock(&sh->lock);
set_bit(STRIPE_SYNCING, &sh->state);
clear_bit(STRIPE_INSYNC, &sh->state);
@@ -1716,6 +1786,13 @@ static void raid6d (mddev_t *mddev)
while (1) {
struct list_head *first;
+ if (conf->seq_flush - conf->seq_write > 0) {
+ int seq = conf->seq_flush;
+ bitmap_unplug(mddev->bitmap);
+ conf->seq_write = seq;
+ activate_bit_delay(conf);
+ }
+
if (list_empty(&conf->handle_list) &&
atomic_read(&conf->preread_active_stripes) < IO_THRESHOLD &&
!blk_queue_plugged(mddev->queue) &&
@@ -1749,7 +1826,7 @@ static void raid6d (mddev_t *mddev)
PRINTK("--- raid6d inactive\n");
}
-static int run (mddev_t *mddev)
+static int run(mddev_t *mddev)
{
raid6_conf_t *conf;
int raid_disk, memory;
@@ -1779,6 +1856,7 @@ static int run (mddev_t *mddev)
init_waitqueue_head(&conf->wait_for_overlap);
INIT_LIST_HEAD(&conf->handle_list);
INIT_LIST_HEAD(&conf->delayed_list);
+ INIT_LIST_HEAD(&conf->bitmap_list);
INIT_LIST_HEAD(&conf->inactive_list);
atomic_set(&conf->active_stripes, 0);
atomic_set(&conf->preread_active_stripes, 0);
@@ -1898,6 +1976,9 @@ static int run (mddev_t *mddev)
/* Ok, everything is just fine now */
mddev->array_size = mddev->size * (mddev->raid_disks - 2);
+ if (mddev->bitmap)
+ mddev->thread->timeout = mddev->bitmap->daemon_sleep * HZ;
+
mddev->queue->unplug_fn = raid6_unplug_device;
mddev->queue->issue_flush_fn = raid6_issue_flush;
return 0;
@@ -2075,6 +2156,8 @@ static int raid6_add_disk(mddev_t *mddev
rdev->in_sync = 0;
rdev->raid_disk = disk;
found = 1;
+ if (rdev->saved_raid_disk != disk)
+ conf->fullsync = 1;
p->rdev = rdev;
break;
}
@@ -2104,6 +2187,35 @@ static int raid6_resize(mddev_t *mddev,
return 0;
}
+static void raid6_quiesce(mddev_t *mddev, int state)
+{
+ raid6_conf_t *conf = mddev_to_conf(mddev);
+
+ switch(state) {
+ case 1: /* stop all writes */
+ spin_lock_irq(&conf->device_lock);
+ conf->quiesce = 1;
+ wait_event_lock_irq(conf->wait_for_stripe,
+ atomic_read(&conf->active_stripes) == 0,
+ conf->device_lock, /* nothing */);
+ spin_unlock_irq(&conf->device_lock);
+ break;
+
+ case 0: /* re-enable writes */
+ spin_lock_irq(&conf->device_lock);
+ conf->quiesce = 0;
+ wake_up(&conf->wait_for_stripe);
+ spin_unlock_irq(&conf->device_lock);
+ break;
+ }
+ if (mddev->thread) {
+ if (mddev->bitmap)
+ mddev->thread->timeout = mddev->bitmap->daemon_sleep * HZ;
+ else
+ mddev->thread->timeout = MAX_SCHEDULE_TIMEOUT;
+ md_wakeup_thread(mddev->thread);
+ }
+}
static mdk_personality_t raid6_personality=
{
.name = "raid6",
@@ -2118,6 +2230,7 @@ static mdk_personality_t raid6_personali
.spare_active = raid6_spare_active,
.sync_request = sync_request,
.resize = raid6_resize,
+ .quiesce = raid6_quiesce,
};
static int __init raid6_init (void)
^ permalink raw reply [flat|nested] 12+ messages in thread* [PATCH md 003 of 7] Add write-intent-bitmap support to raid5
2005-08-29 7:33 [PATCH md 000 of 7] Introduction NeilBrown
` (3 preceding siblings ...)
2005-08-29 7:33 ` [PATCH md 004 of 7] write-intent bitmap support for raid6 NeilBrown
@ 2005-08-29 7:33 ` NeilBrown
2005-08-29 7:33 ` [PATCH md 002 of 7] Limit size of sb read/written to appropriate amount NeilBrown
2005-08-29 7:33 ` [PATCH md 005 of 7] Use kthread infrastructure in md NeilBrown
6 siblings, 0 replies; 12+ messages in thread
From: NeilBrown @ 2005-08-29 7:33 UTC (permalink / raw)
To: Andrew Morton; +Cc: linux-raid
Most awkward part of this is delaying write requests until bitmap
updates have been flushed.
To achieve this, we have a sequence number (seq_flush) which is incremented
each time the raid5 is unplugged.
If the raid thread notices that this has changed, it flushes
bitmap changes, and assigned the value of seq_flush to seq_write.
When a write request arrives, it is given the number from seq_write, and
that write request may not complete until seq_flush is larger than the saved
seq number.
We have a new queue for storing stripes which are waiting for a bitmap
flush and an extra flag for stripes to record if the write was 'degraded'
and so should not clear the a bit in the bitmap.
Signed-off-by: Neil Brown <neilb@cse.unsw.edu.au>
### Diffstat output
./drivers/md/md.c | 3
./drivers/md/raid5.c | 133 +++++++++++++++++++++++++++++++++++++++----
./include/linux/raid/raid5.h | 14 ++++
3 files changed, 137 insertions(+), 13 deletions(-)
diff ./drivers/md/md.c~current~ ./drivers/md/md.c
--- ./drivers/md/md.c~current~ 2005-08-29 16:32:20.000000000 +1000
+++ ./drivers/md/md.c 2005-08-29 16:32:24.000000000 +1000
@@ -645,7 +645,7 @@ static int super_90_validate(mddev_t *md
if (sb->state & (1<<MD_SB_BITMAP_PRESENT) &&
mddev->bitmap_file == NULL) {
- if (mddev->level != 1) {
+ if (mddev->level != 1 && mddev->level != 5) {
/* FIXME use a better test */
printk(KERN_WARNING "md: bitmaps only support for raid1\n");
return -EINVAL;
@@ -3517,7 +3517,6 @@ void md_done_sync(mddev_t *mddev, int bl
*/
void md_write_start(mddev_t *mddev, struct bio *bi)
{
- DEFINE_WAIT(w);
if (bio_data_dir(bi) != WRITE)
return;
diff ./drivers/md/raid5.c~current~ ./drivers/md/raid5.c
--- ./drivers/md/raid5.c~current~ 2005-08-29 16:32:20.000000000 +1000
+++ ./drivers/md/raid5.c 2005-08-29 16:32:24.000000000 +1000
@@ -24,6 +24,8 @@
#include <linux/bitops.h>
#include <asm/atomic.h>
+#include <linux/raid/bitmap.h>
+
/*
* Stripe cache
*/
@@ -79,8 +81,13 @@ static inline void __release_stripe(raid
if (test_bit(STRIPE_HANDLE, &sh->state)) {
if (test_bit(STRIPE_DELAYED, &sh->state))
list_add_tail(&sh->lru, &conf->delayed_list);
- else
+ else if (test_bit(STRIPE_BIT_DELAY, &sh->state) &&
+ conf->seq_write == sh->bm_seq)
+ list_add_tail(&sh->lru, &conf->bitmap_list);
+ else {
+ clear_bit(STRIPE_BIT_DELAY, &sh->state);
list_add_tail(&sh->lru, &conf->handle_list);
+ }
md_wakeup_thread(conf->mddev->thread);
} else {
if (test_and_clear_bit(STRIPE_PREREAD_ACTIVE, &sh->state)) {
@@ -244,6 +251,9 @@ static struct stripe_head *get_active_st
spin_lock_irq(&conf->device_lock);
do {
+ wait_event_lock_irq(conf->wait_for_stripe,
+ conf->quiesce == 0,
+ conf->device_lock, /* nothing */);
sh = __find_stripe(conf, sector);
if (!sh) {
if (!conf->inactive_blocked)
@@ -803,6 +813,7 @@ static int add_stripe_bio(struct stripe_
{
struct bio **bip;
raid5_conf_t *conf = sh->raid_conf;
+ int firstwrite=0;
PRINTK("adding bh b#%llu to stripe s#%llu\n",
(unsigned long long)bi->bi_sector,
@@ -811,9 +822,11 @@ static int add_stripe_bio(struct stripe_
spin_lock(&sh->lock);
spin_lock_irq(&conf->device_lock);
- if (forwrite)
+ if (forwrite) {
bip = &sh->dev[dd_idx].towrite;
- else
+ if (*bip == NULL && sh->dev[dd_idx].written == NULL)
+ firstwrite = 1;
+ } else
bip = &sh->dev[dd_idx].toread;
while (*bip && (*bip)->bi_sector < bi->bi_sector) {
if ((*bip)->bi_sector + ((*bip)->bi_size >> 9) > bi->bi_sector)
@@ -836,6 +849,13 @@ static int add_stripe_bio(struct stripe_
(unsigned long long)bi->bi_sector,
(unsigned long long)sh->sector, dd_idx);
+ if (conf->mddev->bitmap && firstwrite) {
+ sh->bm_seq = conf->seq_write;
+ bitmap_startwrite(conf->mddev->bitmap, sh->sector,
+ STRIPE_SECTORS, 0);
+ set_bit(STRIPE_BIT_DELAY, &sh->state);
+ }
+
if (forwrite) {
/* check if page is covered */
sector_t sector = sh->dev[dd_idx].sector;
@@ -958,12 +978,13 @@ static void handle_stripe(struct stripe_
* need to be failed
*/
if (failed > 1 && to_read+to_write+written) {
- spin_lock_irq(&conf->device_lock);
for (i=disks; i--; ) {
+ int bitmap_end = 0;
+ spin_lock_irq(&conf->device_lock);
/* fail all writes first */
bi = sh->dev[i].towrite;
sh->dev[i].towrite = NULL;
- if (bi) to_write--;
+ if (bi) { to_write--; bitmap_end = 1; }
if (test_and_clear_bit(R5_Overlap, &sh->dev[i].flags))
wake_up(&conf->wait_for_overlap);
@@ -981,6 +1002,7 @@ static void handle_stripe(struct stripe_
/* and fail all 'written' */
bi = sh->dev[i].written;
sh->dev[i].written = NULL;
+ if (bi) bitmap_end = 1;
while (bi && bi->bi_sector < sh->dev[i].sector + STRIPE_SECTORS) {
struct bio *bi2 = r5_next_bio(bi, sh->dev[i].sector);
clear_bit(BIO_UPTODATE, &bi->bi_flags);
@@ -1009,8 +1031,11 @@ static void handle_stripe(struct stripe_
bi = nextbi;
}
}
+ spin_unlock_irq(&conf->device_lock);
+ if (bitmap_end)
+ bitmap_endwrite(conf->mddev->bitmap, sh->sector,
+ STRIPE_SECTORS, 0, 0);
}
- spin_unlock_irq(&conf->device_lock);
}
if (failed > 1 && syncing) {
md_done_sync(conf->mddev, STRIPE_SECTORS,0);
@@ -1038,6 +1063,7 @@ static void handle_stripe(struct stripe_
test_bit(R5_UPTODATE, &dev->flags) ) {
/* We can return any write requests */
struct bio *wbi, *wbi2;
+ int bitmap_end = 0;
PRINTK("Return write for disc %d\n", i);
spin_lock_irq(&conf->device_lock);
wbi = dev->written;
@@ -1051,7 +1077,13 @@ static void handle_stripe(struct stripe_
}
wbi = wbi2;
}
+ if (dev->towrite == NULL)
+ bitmap_end = 1;
spin_unlock_irq(&conf->device_lock);
+ if (bitmap_end)
+ bitmap_endwrite(conf->mddev->bitmap, sh->sector,
+ STRIPE_SECTORS,
+ !test_bit(STRIPE_DEGRADED, &sh->state), 0);
}
}
}
@@ -1175,7 +1207,8 @@ static void handle_stripe(struct stripe_
}
}
/* now if nothing is locked, and if we have enough data, we can start a write request */
- if (locked == 0 && (rcw == 0 ||rmw == 0)) {
+ if (locked == 0 && (rcw == 0 ||rmw == 0) &&
+ !test_bit(STRIPE_BIT_DELAY, &sh->state)) {
PRINTK("Computing parity...\n");
compute_parity(sh, rcw==0 ? RECONSTRUCT_WRITE : READ_MODIFY_WRITE);
/* now every locked buffer is ready to be written */
@@ -1231,6 +1264,7 @@ static void handle_stripe(struct stripe_
dev = &sh->dev[failed_num];
set_bit(R5_LOCKED, &dev->flags);
set_bit(R5_Wantwrite, &dev->flags);
+ clear_bit(STRIPE_DEGRADED, &sh->state);
locked++;
set_bit(STRIPE_INSYNC, &sh->state);
set_bit(R5_Syncio, &dev->flags);
@@ -1298,6 +1332,8 @@ static void handle_stripe(struct stripe_
bi->bi_next = NULL;
generic_make_request(bi);
} else {
+ if (rw == 1)
+ set_bit(STRIPE_DEGRADED, &sh->state);
PRINTK("skip op %ld on disc %d for sector %llu\n",
bi->bi_rw, i, (unsigned long long)sh->sector);
clear_bit(R5_LOCKED, &sh->dev[i].flags);
@@ -1322,6 +1358,20 @@ static inline void raid5_activate_delaye
}
}
+static inline void activate_bit_delay(raid5_conf_t *conf)
+{
+ /* device_lock is held */
+ struct list_head head;
+ list_add(&head, &conf->bitmap_list);
+ list_del_init(&conf->bitmap_list);
+ while (!list_empty(&head)) {
+ struct stripe_head *sh = list_entry(head.next, struct stripe_head, lru);
+ list_del_init(&sh->lru);
+ atomic_inc(&sh->count);
+ __release_stripe(conf, sh);
+ }
+}
+
static void unplug_slaves(mddev_t *mddev)
{
raid5_conf_t *conf = mddev_to_conf(mddev);
@@ -1354,8 +1404,10 @@ static void raid5_unplug_device(request_
spin_lock_irqsave(&conf->device_lock, flags);
- if (blk_remove_plug(q))
+ if (blk_remove_plug(q)) {
+ conf->seq_flush++;
raid5_activate_delayed(conf);
+ }
md_wakeup_thread(mddev->thread);
spin_unlock_irqrestore(&conf->device_lock, flags);
@@ -1493,10 +1545,20 @@ static sector_t sync_request(mddev_t *md
sector_t first_sector;
int raid_disks = conf->raid_disks;
int data_disks = raid_disks-1;
+ sector_t max_sector = mddev->size << 1;
+ int sync_blocks;
- if (sector_nr >= mddev->size <<1) {
+ if (sector_nr >= max_sector) {
/* just being told to finish up .. nothing much to do */
unplug_slaves(mddev);
+
+ if (mddev->curr_resync < max_sector) /* aborted */
+ bitmap_end_sync(mddev->bitmap, mddev->curr_resync,
+ &sync_blocks, 1);
+ else /* compelted sync */
+ conf->fullsync = 0;
+ bitmap_close_sync(mddev->bitmap);
+
return 0;
}
/* if there is 1 or more failed drives and we are trying
@@ -1508,6 +1570,13 @@ static sector_t sync_request(mddev_t *md
*skipped = 1;
return rv;
}
+ if (!bitmap_start_sync(mddev->bitmap, sector_nr, &sync_blocks, 1) &&
+ !conf->fullsync && sync_blocks >= STRIPE_SECTORS) {
+ /* we can skip this block, and probably more */
+ sync_blocks /= STRIPE_SECTORS;
+ *skipped = 1;
+ return sync_blocks * STRIPE_SECTORS; /* keep things rounded to whole stripes */
+ }
x = sector_nr;
chunk_offset = sector_div(x, sectors_per_chunk);
@@ -1524,6 +1593,7 @@ static sector_t sync_request(mddev_t *md
*/
schedule_timeout_uninterruptible(1);
}
+ bitmap_start_sync(mddev->bitmap, sector_nr, &sync_blocks, 0);
spin_lock(&sh->lock);
set_bit(STRIPE_SYNCING, &sh->state);
clear_bit(STRIPE_INSYNC, &sh->state);
@@ -1557,6 +1627,13 @@ static void raid5d (mddev_t *mddev)
while (1) {
struct list_head *first;
+ if (conf->seq_flush - conf->seq_write > 0) {
+ int seq = conf->seq_flush;
+ bitmap_unplug(mddev->bitmap);
+ conf->seq_write = seq;
+ activate_bit_delay(conf);
+ }
+
if (list_empty(&conf->handle_list) &&
atomic_read(&conf->preread_active_stripes) < IO_THRESHOLD &&
!blk_queue_plugged(mddev->queue) &&
@@ -1590,7 +1667,7 @@ static void raid5d (mddev_t *mddev)
PRINTK("--- raid5d inactive\n");
}
-static int run (mddev_t *mddev)
+static int run(mddev_t *mddev)
{
raid5_conf_t *conf;
int raid_disk, memory;
@@ -1620,6 +1697,7 @@ static int run (mddev_t *mddev)
init_waitqueue_head(&conf->wait_for_overlap);
INIT_LIST_HEAD(&conf->handle_list);
INIT_LIST_HEAD(&conf->delayed_list);
+ INIT_LIST_HEAD(&conf->bitmap_list);
INIT_LIST_HEAD(&conf->inactive_list);
atomic_set(&conf->active_stripes, 0);
atomic_set(&conf->preread_active_stripes, 0);
@@ -1731,6 +1809,9 @@ memory = conf->max_nr_stripes * (sizeof(
/* Ok, everything is just fine now */
+ if (mddev->bitmap)
+ mddev->thread->timeout = mddev->bitmap->daemon_sleep * HZ;
+
mddev->queue->unplug_fn = raid5_unplug_device;
mddev->queue->issue_flush_fn = raid5_issue_flush;
@@ -1911,6 +1992,8 @@ static int raid5_add_disk(mddev_t *mddev
rdev->in_sync = 0;
rdev->raid_disk = disk;
found = 1;
+ if (rdev->saved_raid_disk != disk)
+ conf->fullsync = 1;
p->rdev = rdev;
break;
}
@@ -1940,6 +2023,35 @@ static int raid5_resize(mddev_t *mddev,
return 0;
}
+static void raid5_quiesce(mddev_t *mddev, int state)
+{
+ raid5_conf_t *conf = mddev_to_conf(mddev);
+
+ switch(state) {
+ case 1: /* stop all writes */
+ spin_lock_irq(&conf->device_lock);
+ conf->quiesce = 1;
+ wait_event_lock_irq(conf->wait_for_stripe,
+ atomic_read(&conf->active_stripes) == 0,
+ conf->device_lock, /* nothing */);
+ spin_unlock_irq(&conf->device_lock);
+ break;
+
+ case 0: /* re-enable writes */
+ spin_lock_irq(&conf->device_lock);
+ conf->quiesce = 0;
+ wake_up(&conf->wait_for_stripe);
+ spin_unlock_irq(&conf->device_lock);
+ break;
+ }
+ if (mddev->thread) {
+ if (mddev->bitmap)
+ mddev->thread->timeout = mddev->bitmap->daemon_sleep * HZ;
+ else
+ mddev->thread->timeout = MAX_SCHEDULE_TIMEOUT;
+ md_wakeup_thread(mddev->thread);
+ }
+}
static mdk_personality_t raid5_personality=
{
.name = "raid5",
@@ -1954,6 +2066,7 @@ static mdk_personality_t raid5_personali
.spare_active = raid5_spare_active,
.sync_request = sync_request,
.resize = raid5_resize,
+ .quiesce = raid5_quiesce,
};
static int __init raid5_init (void)
diff ./include/linux/raid/raid5.h~current~ ./include/linux/raid/raid5.h
--- ./include/linux/raid/raid5.h~current~ 2005-08-29 16:32:20.000000000 +1000
+++ ./include/linux/raid/raid5.h 2005-08-29 16:32:24.000000000 +1000
@@ -134,6 +134,7 @@ struct stripe_head {
unsigned long state; /* state flags */
atomic_t count; /* nr of active thread/requests */
spinlock_t lock;
+ int bm_seq; /* sequence number for bitmap flushes */
struct r5dev {
struct bio req;
struct bio_vec vec;
@@ -165,12 +166,13 @@ struct stripe_head {
/*
* Stripe state
*/
-#define STRIPE_ERROR 1
#define STRIPE_HANDLE 2
#define STRIPE_SYNCING 3
#define STRIPE_INSYNC 4
#define STRIPE_PREREAD_ACTIVE 5
#define STRIPE_DELAYED 6
+#define STRIPE_DEGRADED 7
+#define STRIPE_BIT_DELAY 8
/*
* Plugging:
@@ -210,10 +212,20 @@ struct raid5_private_data {
struct list_head handle_list; /* stripes needing handling */
struct list_head delayed_list; /* stripes that have plugged requests */
+ struct list_head bitmap_list; /* stripes delaying awaiting bitmap update */
atomic_t preread_active_stripes; /* stripes with scheduled io */
char cache_name[20];
kmem_cache_t *slab_cache; /* for allocating stripes */
+
+ int seq_flush, seq_write;
+ int quiesce;
+
+ int fullsync; /* set to 1 if a full sync is needed,
+ * (fresh device added).
+ * Cleared when a sync completes.
+ */
+
/*
* Free stripes pool
*/
^ permalink raw reply [flat|nested] 12+ messages in thread* [PATCH md 002 of 7] Limit size of sb read/written to appropriate amount.
2005-08-29 7:33 [PATCH md 000 of 7] Introduction NeilBrown
` (4 preceding siblings ...)
2005-08-29 7:33 ` [PATCH md 003 of 7] Add write-intent-bitmap support to raid5 NeilBrown
@ 2005-08-29 7:33 ` NeilBrown
2005-08-29 7:33 ` [PATCH md 005 of 7] Use kthread infrastructure in md NeilBrown
6 siblings, 0 replies; 12+ messages in thread
From: NeilBrown @ 2005-08-29 7:33 UTC (permalink / raw)
To: Andrew Morton; +Cc: linux-raid
version-1 superblocks are not (normally) 4K long, and can be of
variable size. Writing the full 4K can cause corruption (but only in
non-default configurations).
With this patch the super-block-flavour can choose a size to read, and
set a size to write based on what it finds.
Signed-off-by: Neil Brown <neilb@cse.unsw.edu.au>
### Diffstat output
./drivers/md/md.c | 20 +++++++++++++++-----
./include/linux/raid/md_k.h | 1 +
2 files changed, 16 insertions(+), 5 deletions(-)
diff ./drivers/md/md.c~current~ ./drivers/md/md.c
--- ./drivers/md/md.c~current~ 2005-08-29 15:52:32.000000000 +1000
+++ ./drivers/md/md.c 2005-08-29 15:52:47.000000000 +1000
@@ -393,7 +393,7 @@ int sync_page_io(struct block_device *bd
return ret;
}
-static int read_disk_sb(mdk_rdev_t * rdev)
+static int read_disk_sb(mdk_rdev_t * rdev, int size)
{
char b[BDEVNAME_SIZE];
if (!rdev->sb_page) {
@@ -404,7 +404,7 @@ static int read_disk_sb(mdk_rdev_t * rde
return 0;
- if (!sync_page_io(rdev->bdev, rdev->sb_offset<<1, MD_SB_BYTES, rdev->sb_page, READ))
+ if (!sync_page_io(rdev->bdev, rdev->sb_offset<<1, size, rdev->sb_page, READ))
goto fail;
rdev->sb_loaded = 1;
return 0;
@@ -531,7 +531,7 @@ static int super_90_load(mdk_rdev_t *rde
sb_offset = calc_dev_sboffset(rdev->bdev);
rdev->sb_offset = sb_offset;
- ret = read_disk_sb(rdev);
+ ret = read_disk_sb(rdev, MD_SB_BYTES);
if (ret) return ret;
ret = -EINVAL;
@@ -564,6 +564,7 @@ static int super_90_load(mdk_rdev_t *rde
rdev->preferred_minor = sb->md_minor;
rdev->data_offset = 0;
+ rdev->sb_size = MD_SB_BYTES;
if (sb->level == LEVEL_MULTIPATH)
rdev->desc_nr = -1;
@@ -837,6 +838,7 @@ static int super_1_load(mdk_rdev_t *rdev
int ret;
sector_t sb_offset;
char b[BDEVNAME_SIZE], b2[BDEVNAME_SIZE];
+ int bmask;
/*
* Calculate the position of the superblock.
@@ -865,7 +867,10 @@ static int super_1_load(mdk_rdev_t *rdev
}
rdev->sb_offset = sb_offset;
- ret = read_disk_sb(rdev);
+ /* superblock is rarely larger than 1K, but it can be larger,
+ * and it is safe to read 4k, so we do that
+ */
+ ret = read_disk_sb(rdev, 4096);
if (ret) return ret;
@@ -891,6 +896,11 @@ static int super_1_load(mdk_rdev_t *rdev
rdev->preferred_minor = 0xffff;
rdev->data_offset = le64_to_cpu(sb->data_offset);
+ rdev->sb_size = le32_to_cpu(sb->max_dev) * 2 + 256;
+ bmask = block_size(rdev->bdev)-1;
+ if (rdev->sb_size & bmask)
+ rdev-> sb_size = (rdev->sb_size | bmask)+1;
+
if (refdev == 0)
return 1;
else {
@@ -1375,7 +1385,7 @@ repeat:
dprintk("%s ", bdevname(rdev->bdev,b));
if (!rdev->faulty) {
md_super_write(mddev,rdev,
- rdev->sb_offset<<1, MD_SB_BYTES,
+ rdev->sb_offset<<1, rdev->sb_size,
rdev->sb_page);
dprintk(KERN_INFO "(write) %s's sb offset: %llu\n",
bdevname(rdev->bdev,b),
diff ./include/linux/raid/md_k.h~current~ ./include/linux/raid/md_k.h
--- ./include/linux/raid/md_k.h~current~ 2005-08-29 15:52:38.000000000 +1000
+++ ./include/linux/raid/md_k.h 2005-08-29 15:52:47.000000000 +1000
@@ -102,6 +102,7 @@ struct mdk_rdev_s
int sb_loaded;
sector_t data_offset; /* start of data in array */
sector_t sb_offset;
+ int sb_size; /* bytes in the superblock */
int preferred_minor; /* autorun support */
/* A device can be in one of three states based on two flags:
^ permalink raw reply [flat|nested] 12+ messages in thread* [PATCH md 005 of 7] Use kthread infrastructure in md
2005-08-29 7:33 [PATCH md 000 of 7] Introduction NeilBrown
` (5 preceding siblings ...)
2005-08-29 7:33 ` [PATCH md 002 of 7] Limit size of sb read/written to appropriate amount NeilBrown
@ 2005-08-29 7:33 ` NeilBrown
6 siblings, 0 replies; 12+ messages in thread
From: NeilBrown @ 2005-08-29 7:33 UTC (permalink / raw)
To: Andrew Morton; +Cc: linux-raid
Switch MD to use the kthread infrastructure, to simplify the code and
get rid of tasklist_lock abuse in md_unregister_thread.
Also don't flush signals in md_thread, as the called thread will
always do that.
Signed-off-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Neil Brown <neilb@cse.unsw.edu.au>
### Diffstat output
./drivers/md/md.c | 48 ++++++++++--------------------------------------
1 file changed, 10 insertions(+), 38 deletions(-)
diff ./drivers/md/md.c~current~ ./drivers/md/md.c
--- ./drivers/md/md.c~current~ 2005-08-29 16:37:35.000000000 +1000
+++ ./drivers/md/md.c 2005-08-29 16:37:40.000000000 +1000
@@ -34,6 +34,7 @@
#include <linux/module.h>
#include <linux/config.h>
+#include <linux/kthread.h>
#include <linux/linkage.h>
#include <linux/raid/md.h>
#include <linux/raid/bitmap.h>
@@ -3049,18 +3050,6 @@ static int md_thread(void * arg)
{
mdk_thread_t *thread = arg;
- lock_kernel();
-
- /*
- * Detach thread
- */
-
- daemonize(thread->name, mdname(thread->mddev));
-
- current->exit_signal = SIGCHLD;
- allow_signal(SIGKILL);
- thread->tsk = current;
-
/*
* md_thread is a 'system-thread', it's priority should be very
* high. We avoid resource deadlocks individually in each
@@ -3072,14 +3061,14 @@ static int md_thread(void * arg)
* bdflush, otherwise bdflush will deadlock if there are too
* many dirty RAID5 blocks.
*/
- unlock_kernel();
complete(thread->event);
- while (thread->run) {
+ while (!kthread_should_stop()) {
void (*run)(mddev_t *);
wait_event_interruptible_timeout(thread->wqueue,
- test_bit(THREAD_WAKEUP, &thread->flags),
+ test_bit(THREAD_WAKEUP, &thread->flags)
+ || kthread_should_stop(),
thread->timeout);
try_to_freeze();
@@ -3088,11 +3077,8 @@ static int md_thread(void * arg)
run = thread->run;
if (run)
run(thread->mddev);
-
- if (signal_pending(current))
- flush_signals(current);
}
- complete(thread->event);
+
return 0;
}
@@ -3109,11 +3095,9 @@ mdk_thread_t *md_register_thread(void (*
const char *name)
{
mdk_thread_t *thread;
- int ret;
struct completion event;
- thread = (mdk_thread_t *) kmalloc
- (sizeof(mdk_thread_t), GFP_KERNEL);
+ thread = kmalloc(sizeof(mdk_thread_t), GFP_KERNEL);
if (!thread)
return NULL;
@@ -3126,8 +3110,8 @@ mdk_thread_t *md_register_thread(void (*
thread->mddev = mddev;
thread->name = name;
thread->timeout = MAX_SCHEDULE_TIMEOUT;
- ret = kernel_thread(md_thread, thread, 0);
- if (ret < 0) {
+ thread->tsk = kthread_run(md_thread, thread, mdname(thread->mddev));
+ if (IS_ERR(thread->tsk)) {
kfree(thread);
return NULL;
}
@@ -3137,21 +3121,9 @@ mdk_thread_t *md_register_thread(void (*
void md_unregister_thread(mdk_thread_t *thread)
{
- struct completion event;
-
- init_completion(&event);
-
- thread->event = &event;
-
- /* As soon as ->run is set to NULL, the task could disappear,
- * so we need to hold tasklist_lock until we have sent the signal
- */
dprintk("interrupting MD-thread pid %d\n", thread->tsk->pid);
- read_lock(&tasklist_lock);
- thread->run = NULL;
- send_sig(SIGKILL, thread->tsk, 1);
- read_unlock(&tasklist_lock);
- wait_for_completion(&event);
+
+ kthread_stop(thread->tsk);
kfree(thread);
}
^ permalink raw reply [flat|nested] 12+ messages in thread