summaryrefslogtreecommitdiff
path: root/drivers/md/dm-raid1.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/md/dm-raid1.c')
-rw-r--r--drivers/md/dm-raid1.c92
1 files changed, 56 insertions, 36 deletions
diff --git a/drivers/md/dm-raid1.c b/drivers/md/dm-raid1.c
index 06a38dc32025..bc417a5e5b89 100644
--- a/drivers/md/dm-raid1.c
+++ b/drivers/md/dm-raid1.c
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (C) 2003 Sistina Software Limited.
* Copyright (C) 2005-2008 Red Hat, Inc. All rights reserved.
@@ -19,6 +20,8 @@
#include <linux/dm-kcopyd.h>
#include <linux/dm-region-hash.h>
+static struct workqueue_struct *dm_raid1_wq;
+
#define DM_MSG_PREFIX "raid1"
#define MAX_RECOVERY 1 /* Maximum number of regions recovered in parallel. */
@@ -32,9 +35,11 @@
static DECLARE_WAIT_QUEUE_HEAD(_kmirrord_recovery_stopped);
-/*-----------------------------------------------------------------
+/*
+ *---------------------------------------------------------------
* Mirror set structures.
- *---------------------------------------------------------------*/
+ *---------------------------------------------------------------
+ */
enum dm_raid1_error {
DM_RAID1_WRITE_ERROR,
DM_RAID1_FLUSH_ERROR,
@@ -82,7 +87,7 @@ struct mirror_set {
struct work_struct trigger_event;
- unsigned nr_mirrors;
+ unsigned int nr_mirrors;
struct mirror mirror[];
};
@@ -236,8 +241,8 @@ static void fail_mirror(struct mirror *m, enum dm_raid1_error error_type)
* Better to issue requests to same failing device
* than to risk returning corrupt data.
*/
- DMERR("Primary mirror (%s) failed while out-of-sync: "
- "Reads may fail.", m->dev->name);
+ DMERR("Primary mirror (%s) failed while out-of-sync: Reads may fail.",
+ m->dev->name);
goto out;
}
@@ -248,7 +253,7 @@ static void fail_mirror(struct mirror *m, enum dm_raid1_error error_type)
DMWARN("All sides of mirror have failed.");
out:
- schedule_work(&ms->trigger_event);
+ queue_work(dm_raid1_wq, &ms->trigger_event);
}
static int mirror_flush(struct dm_target *ti)
@@ -285,13 +290,15 @@ static int mirror_flush(struct dm_target *ti)
return 0;
}
-/*-----------------------------------------------------------------
+/*
+ *---------------------------------------------------------------
* Recovery.
*
* When a mirror is first activated we may find that some regions
* are in the no-sync state. We have to recover these by
* recopying from the default mirror to all the others.
- *---------------------------------------------------------------*/
+ *---------------------------------------------------------------
+ */
static void recovery_complete(int read_err, unsigned long write_err,
void *context)
{
@@ -327,7 +334,7 @@ static void recovery_complete(int read_err, unsigned long write_err,
static void recover(struct mirror_set *ms, struct dm_region *reg)
{
- unsigned i;
+ unsigned int i;
struct dm_io_region from, to[DM_KCOPYD_MAX_REGIONS], *dest;
struct mirror *m;
unsigned long flags = 0;
@@ -408,9 +415,11 @@ static void do_recovery(struct mirror_set *ms)
}
}
-/*-----------------------------------------------------------------
+/*
+ *---------------------------------------------------------------
* Reads
- *---------------------------------------------------------------*/
+ *---------------------------------------------------------------
+ */
static struct mirror *choose_mirror(struct mirror_set *ms, sector_t sector)
{
struct mirror *m = get_default_mirror(ms);
@@ -498,9 +507,11 @@ static void hold_bio(struct mirror_set *ms, struct bio *bio)
spin_unlock_irq(&ms->lock);
}
-/*-----------------------------------------------------------------
+/*
+ *---------------------------------------------------------------
* Reads
- *---------------------------------------------------------------*/
+ *---------------------------------------------------------------
+ */
static void read_callback(unsigned long error, void *context)
{
struct bio *bio = context;
@@ -517,8 +528,7 @@ static void read_callback(unsigned long error, void *context)
fail_mirror(m, DM_RAID1_READ_ERROR);
if (likely(default_ok(m)) || mirror_available(m->ms, bio)) {
- DMWARN_LIMIT("Read failure on mirror device %s. "
- "Trying alternative device.",
+ DMWARN_LIMIT("Read failure on mirror device %s. Trying alternative device.",
m->dev->name);
queue_bio(m->ms, bio, bio_data_dir(bio));
return;
@@ -579,21 +589,21 @@ static void do_reads(struct mirror_set *ms, struct bio_list *reads)
}
}
-/*-----------------------------------------------------------------
+/*
+ *---------------------------------------------------------------------
* Writes.
*
* We do different things with the write io depending on the
* state of the region that it's in:
*
- * SYNC: increment pending, use kcopyd to write to *all* mirrors
+ * SYNC: increment pending, use kcopyd to write to *all* mirrors
* RECOVERING: delay the io until recovery completes
* NOSYNC: increment pending, just write to the default mirror
- *---------------------------------------------------------------*/
-
-
+ *---------------------------------------------------------------------
+ */
static void write_callback(unsigned long error, void *context)
{
- unsigned i;
+ unsigned int i;
struct bio *bio = (struct bio *) context;
struct mirror_set *ms;
int should_wake = 0;
@@ -842,9 +852,11 @@ static void trigger_event(struct work_struct *work)
dm_table_event(ms->ti->table);
}
-/*-----------------------------------------------------------------
+/*
+ *---------------------------------------------------------------
* kmirrord
- *---------------------------------------------------------------*/
+ *---------------------------------------------------------------
+ */
static void do_mirror(struct work_struct *work)
{
struct mirror_set *ms = container_of(work, struct mirror_set,
@@ -868,9 +880,11 @@ static void do_mirror(struct work_struct *work)
do_failures(ms, &failures);
}
-/*-----------------------------------------------------------------
+/*
+ *---------------------------------------------------------------
* Target functions
- *---------------------------------------------------------------*/
+ *---------------------------------------------------------------
+ */
static struct mirror_set *alloc_context(unsigned int nr_mirrors,
uint32_t region_size,
struct dm_target *ti,
@@ -903,7 +917,7 @@ static struct mirror_set *alloc_context(unsigned int nr_mirrors,
if (IS_ERR(ms->io_client)) {
ti->error = "Error creating dm_io client";
kfree(ms);
- return NULL;
+ return NULL;
}
ms->rh = dm_region_hash_create(ms, dispatch_bios, wakeup_mirrord,
@@ -963,10 +977,10 @@ static int get_mirror(struct mirror_set *ms, struct dm_target *ti,
* Create dirty log: log_type #log_params <log_params>
*/
static struct dm_dirty_log *create_dirty_log(struct dm_target *ti,
- unsigned argc, char **argv,
- unsigned *args_used)
+ unsigned int argc, char **argv,
+ unsigned int *args_used)
{
- unsigned param_count;
+ unsigned int param_count;
struct dm_dirty_log *dl;
char dummy;
@@ -997,10 +1011,10 @@ static struct dm_dirty_log *create_dirty_log(struct dm_target *ti,
return dl;
}
-static int parse_features(struct mirror_set *ms, unsigned argc, char **argv,
- unsigned *args_used)
+static int parse_features(struct mirror_set *ms, unsigned int argc, char **argv,
+ unsigned int *args_used)
{
- unsigned num_features;
+ unsigned int num_features;
struct dm_target *ti = ms->ti;
char dummy;
int i;
@@ -1389,7 +1403,7 @@ static char device_status_char(struct mirror *m)
static void mirror_status(struct dm_target *ti, status_type_t type,
- unsigned status_flags, char *result, unsigned maxlen)
+ unsigned int status_flags, char *result, unsigned int maxlen)
{
unsigned int m, sz = 0;
int num_feature_args = 0;
@@ -1458,7 +1472,7 @@ static int mirror_iterate_devices(struct dm_target *ti,
{
struct mirror_set *ms = ti->private;
int ret = 0;
- unsigned i;
+ unsigned int i;
for (i = 0; !ret && i < ms->nr_mirrors; i++)
ret = fn(ti, ms->mirror[i].dev,
@@ -1484,22 +1498,28 @@ static struct target_type mirror_target = {
static int __init dm_mirror_init(void)
{
- int r;
+ int r = -ENOMEM;
+
+ dm_raid1_wq = alloc_workqueue("dm_raid1_wq", 0, 0);
+ if (!dm_raid1_wq)
+ goto bad_target;
r = dm_register_target(&mirror_target);
if (r < 0) {
- DMERR("Failed to register mirror target");
+ destroy_workqueue(dm_raid1_wq);
goto bad_target;
}
return 0;
bad_target:
+ DMERR("Failed to register mirror target");
return r;
}
static void __exit dm_mirror_exit(void)
{
+ destroy_workqueue(dm_raid1_wq);
dm_unregister_target(&mirror_target);
}