diff options
Diffstat (limited to 'drivers/md/dm-raid1.c')
-rw-r--r-- | drivers/md/dm-raid1.c | 92 |
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); } |