Skip to content

Commit

Permalink
dm raid1: add is_remote_recovering hook for clusters
Browse files Browse the repository at this point in the history
The logging API needs an extra function to make cluster mirroring
possible.  This new function allows us to check whether a mirror
region is being recovered on another machine in the cluster.  This
helps us prevent simultaneous recovery I/O and process I/O to the
same locations on disk.

Cluster-aware log modules will implement this function.  Single
machine log modules will not.  So, there is no performance
penalty for single machine mirrors.

Signed-off-by: Jonathan Brassow <jbrassow@redhat.com>
Acked-by: Heinz Mauelshagen <heinzm@redhat.com>
Signed-off-by: Alasdair G Kergon <agk@redhat.com>
  • Loading branch information
Jonathan Brassow authored and Alasdair G Kergon committed Apr 2, 2009
1 parent b2a1146 commit 7513c2a
Show file tree
Hide file tree
Showing 2 changed files with 33 additions and 2 deletions.
25 changes: 23 additions & 2 deletions drivers/md/dm-raid1.c
Original file line number Diff line number Diff line change
Expand Up @@ -588,6 +588,9 @@ static void do_writes(struct mirror_set *ms, struct bio_list *writes)
int state;
struct bio *bio;
struct bio_list sync, nosync, recover, *this_list = NULL;
struct bio_list requeue;
struct dm_dirty_log *log = dm_rh_dirty_log(ms->rh);
region_t region;

if (!writes->head)
return;
Expand All @@ -598,10 +601,18 @@ static void do_writes(struct mirror_set *ms, struct bio_list *writes)
bio_list_init(&sync);
bio_list_init(&nosync);
bio_list_init(&recover);
bio_list_init(&requeue);

while ((bio = bio_list_pop(writes))) {
state = dm_rh_get_state(ms->rh,
dm_rh_bio_to_region(ms->rh, bio), 1);
region = dm_rh_bio_to_region(ms->rh, bio);

if (log->type->is_remote_recovering &&
log->type->is_remote_recovering(log, region)) {
bio_list_add(&requeue, bio);
continue;
}

state = dm_rh_get_state(ms->rh, region, 1);
switch (state) {
case DM_RH_CLEAN:
case DM_RH_DIRTY:
Expand All @@ -620,6 +631,16 @@ static void do_writes(struct mirror_set *ms, struct bio_list *writes)
bio_list_add(this_list, bio);
}

/*
* Add bios that are delayed due to remote recovery
* back on to the write queue
*/
if (unlikely(requeue.head)) {
spin_lock_irq(&ms->lock);
bio_list_merge(&ms->writes, &requeue);
spin_unlock_irq(&ms->lock);
}

/*
* Increment the pending counts for any regions that will
* be written to (writes to recover regions are going to
Expand Down
10 changes: 10 additions & 0 deletions include/linux/dm-dirty-log.h
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,16 @@ struct dm_dirty_log_type {
*/
int (*status)(struct dm_dirty_log *log, status_type_t status_type,
char *result, unsigned maxlen);

/*
* is_remote_recovering is necessary for cluster mirroring. It provides
* a way to detect recovery on another node, so we aren't writing
* concurrently. This function is likely to block (when a cluster log
* is used).
*
* Returns: 0, 1
*/
int (*is_remote_recovering)(struct dm_dirty_log *log, region_t region);
};

int dm_dirty_log_type_register(struct dm_dirty_log_type *type);
Expand Down

0 comments on commit 7513c2a

Please sign in to comment.