Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 139924
b: refs/heads/master
c: 409c57f
h: refs/heads/master
v: v3
  • Loading branch information
NeilBrown committed Mar 31, 2009
1 parent 2d3cb18 commit 8f6ba79
Show file tree
Hide file tree
Showing 5 changed files with 73 additions and 16 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: e0cf8f045b2023b0b3f919ee93eb94345f648434
refs/heads/master: 409c57f3801701dfee27a28103dda4831306cb20
79 changes: 64 additions & 15 deletions trunk/drivers/md/md.c
Original file line number Diff line number Diff line change
Expand Up @@ -201,12 +201,68 @@ static DEFINE_SPINLOCK(all_mddevs_lock);
)


static int md_fail_request(struct request_queue *q, struct bio *bio)
/* Rather than calling directly into the personality make_request function,
* IO requests come here first so that we can check if the device is
* being suspended pending a reconfiguration.
* We hold a refcount over the call to ->make_request. By the time that
* call has finished, the bio has been linked into some internal structure
* and so is visible to ->quiesce(), so we don't need the refcount any more.
*/
static int md_make_request(struct request_queue *q, struct bio *bio)
{
bio_io_error(bio);
return 0;
mddev_t *mddev = q->queuedata;
int rv;
if (mddev == NULL || mddev->pers == NULL) {
bio_io_error(bio);
return 0;
}
rcu_read_lock();
if (mddev->suspended) {
DEFINE_WAIT(__wait);
for (;;) {
prepare_to_wait(&mddev->sb_wait, &__wait,
TASK_UNINTERRUPTIBLE);
if (!mddev->suspended)
break;
rcu_read_unlock();
schedule();
rcu_read_lock();
}
finish_wait(&mddev->sb_wait, &__wait);
}
atomic_inc(&mddev->active_io);
rcu_read_unlock();
rv = mddev->pers->make_request(q, bio);
if (atomic_dec_and_test(&mddev->active_io) && mddev->suspended)
wake_up(&mddev->sb_wait);

return rv;
}

static void mddev_suspend(mddev_t *mddev)
{
BUG_ON(mddev->suspended);
mddev->suspended = 1;
synchronize_rcu();
wait_event(mddev->sb_wait, atomic_read(&mddev->active_io) == 0);
mddev->pers->quiesce(mddev, 1);
md_unregister_thread(mddev->thread);
mddev->thread = NULL;
/* we now know that no code is executing in the personality module,
* except possibly the tail end of a ->bi_end_io function, but that
* is certain to complete before the module has a chance to get
* unloaded
*/
}

static void mddev_resume(mddev_t *mddev)
{
mddev->suspended = 0;
wake_up(&mddev->sb_wait);
mddev->pers->quiesce(mddev, 0);
}


static inline mddev_t *mddev_get(mddev_t *mddev)
{
atomic_inc(&mddev->active);
Expand Down Expand Up @@ -314,6 +370,7 @@ static mddev_t * mddev_find(dev_t unit)
init_timer(&new->safemode_timer);
atomic_set(&new->active, 1);
atomic_set(&new->openers, 0);
atomic_set(&new->active_io, 0);
spin_lock_init(&new->write_lock);
init_waitqueue_head(&new->sb_wait);
init_waitqueue_head(&new->recovery_wait);
Expand Down Expand Up @@ -3632,10 +3689,12 @@ static int md_alloc(dev_t dev, char *name)
mddev_put(mddev);
return -ENOMEM;
}
mddev->queue->queuedata = mddev;

/* Can be unlocked because the queue is new: no concurrency */
queue_flag_set_unlocked(QUEUE_FLAG_CLUSTER, mddev->queue);

blk_queue_make_request(mddev->queue, md_fail_request);
blk_queue_make_request(mddev->queue, md_make_request);

disk = alloc_disk(1 << shift);
if (!disk) {
Expand Down Expand Up @@ -3938,16 +3997,6 @@ static int do_md_run(mddev_t * mddev)

set_capacity(disk, mddev->array_sectors);

/* If we call blk_queue_make_request here, it will
* re-initialise max_sectors etc which may have been
* refined inside -> run. So just set the bits we need to set.
* Most initialisation happended when we called
* blk_queue_make_request(..., md_fail_request)
* earlier.
*/
mddev->queue->queuedata = mddev;
mddev->queue->make_request_fn = mddev->pers->make_request;

/* If there is a partially-recovered drive we need to
* start recovery here. If we leave it to md_check_recovery,
* it will remove the drives and not do the right thing
Expand Down Expand Up @@ -4077,7 +4126,7 @@ static int do_md_stop(mddev_t * mddev, int mode, int is_open)
md_super_wait(mddev);
if (mddev->ro)
set_disk_ro(disk, 0);
blk_queue_make_request(mddev->queue, md_fail_request);

mddev->pers->stop(mddev);
mddev->queue->merge_bvec_fn = NULL;
mddev->queue->unplug_fn = NULL;
Expand Down
2 changes: 2 additions & 0 deletions trunk/drivers/md/md.h
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,8 @@ struct mddev_s
#define MD_CHANGE_CLEAN 1 /* transition to or from 'clean' */
#define MD_CHANGE_PENDING 2 /* superblock update in progress */

int suspended;
atomic_t active_io;
int ro;

struct gendisk *gendisk;
Expand Down
3 changes: 3 additions & 0 deletions trunk/drivers/md/raid1.c
Original file line number Diff line number Diff line change
Expand Up @@ -2092,6 +2092,9 @@ static int stop(mddev_t *mddev)
/* need to kick something here to make sure I/O goes? */
}

raise_barrier(conf);
lower_barrier(conf);

md_unregister_thread(mddev->thread);
mddev->thread = NULL;
blk_sync_queue(mddev->queue); /* the unplug fn references 'conf'*/
Expand Down
3 changes: 3 additions & 0 deletions trunk/drivers/md/raid10.c
Original file line number Diff line number Diff line change
Expand Up @@ -2211,6 +2211,9 @@ static int stop(mddev_t *mddev)
{
conf_t *conf = mddev_to_conf(mddev);

raise_barrier(conf, 0);
lower_barrier(conf);

md_unregister_thread(mddev->thread);
mddev->thread = NULL;
blk_sync_queue(mddev->queue); /* the unplug fn references 'conf'*/
Expand Down

0 comments on commit 8f6ba79

Please sign in to comment.