18c2ecf20Sopenharmony_ci/* 28c2ecf20Sopenharmony_ci * Copyright (C) 2003 Sistina Software Limited. 38c2ecf20Sopenharmony_ci * Copyright (C) 2005-2008 Red Hat, Inc. All rights reserved. 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * This file is released under the GPL. 68c2ecf20Sopenharmony_ci */ 78c2ecf20Sopenharmony_ci 88c2ecf20Sopenharmony_ci#include "dm-bio-record.h" 98c2ecf20Sopenharmony_ci 108c2ecf20Sopenharmony_ci#include <linux/init.h> 118c2ecf20Sopenharmony_ci#include <linux/mempool.h> 128c2ecf20Sopenharmony_ci#include <linux/module.h> 138c2ecf20Sopenharmony_ci#include <linux/pagemap.h> 148c2ecf20Sopenharmony_ci#include <linux/slab.h> 158c2ecf20Sopenharmony_ci#include <linux/workqueue.h> 168c2ecf20Sopenharmony_ci#include <linux/device-mapper.h> 178c2ecf20Sopenharmony_ci#include <linux/dm-io.h> 188c2ecf20Sopenharmony_ci#include <linux/dm-dirty-log.h> 198c2ecf20Sopenharmony_ci#include <linux/dm-kcopyd.h> 208c2ecf20Sopenharmony_ci#include <linux/dm-region-hash.h> 218c2ecf20Sopenharmony_ci 228c2ecf20Sopenharmony_ci#define DM_MSG_PREFIX "raid1" 238c2ecf20Sopenharmony_ci 248c2ecf20Sopenharmony_ci#define MAX_RECOVERY 1 /* Maximum number of regions recovered in parallel. */ 258c2ecf20Sopenharmony_ci 268c2ecf20Sopenharmony_ci#define MAX_NR_MIRRORS (DM_KCOPYD_MAX_REGIONS + 1) 278c2ecf20Sopenharmony_ci 288c2ecf20Sopenharmony_ci#define DM_RAID1_HANDLE_ERRORS 0x01 298c2ecf20Sopenharmony_ci#define DM_RAID1_KEEP_LOG 0x02 308c2ecf20Sopenharmony_ci#define errors_handled(p) ((p)->features & DM_RAID1_HANDLE_ERRORS) 318c2ecf20Sopenharmony_ci#define keep_log(p) ((p)->features & DM_RAID1_KEEP_LOG) 328c2ecf20Sopenharmony_ci 338c2ecf20Sopenharmony_cistatic DECLARE_WAIT_QUEUE_HEAD(_kmirrord_recovery_stopped); 348c2ecf20Sopenharmony_ci 358c2ecf20Sopenharmony_ci/*----------------------------------------------------------------- 368c2ecf20Sopenharmony_ci * Mirror set structures. 378c2ecf20Sopenharmony_ci *---------------------------------------------------------------*/ 388c2ecf20Sopenharmony_cienum dm_raid1_error { 398c2ecf20Sopenharmony_ci DM_RAID1_WRITE_ERROR, 408c2ecf20Sopenharmony_ci DM_RAID1_FLUSH_ERROR, 418c2ecf20Sopenharmony_ci DM_RAID1_SYNC_ERROR, 428c2ecf20Sopenharmony_ci DM_RAID1_READ_ERROR 438c2ecf20Sopenharmony_ci}; 448c2ecf20Sopenharmony_ci 458c2ecf20Sopenharmony_cistruct mirror { 468c2ecf20Sopenharmony_ci struct mirror_set *ms; 478c2ecf20Sopenharmony_ci atomic_t error_count; 488c2ecf20Sopenharmony_ci unsigned long error_type; 498c2ecf20Sopenharmony_ci struct dm_dev *dev; 508c2ecf20Sopenharmony_ci sector_t offset; 518c2ecf20Sopenharmony_ci}; 528c2ecf20Sopenharmony_ci 538c2ecf20Sopenharmony_cistruct mirror_set { 548c2ecf20Sopenharmony_ci struct dm_target *ti; 558c2ecf20Sopenharmony_ci struct list_head list; 568c2ecf20Sopenharmony_ci 578c2ecf20Sopenharmony_ci uint64_t features; 588c2ecf20Sopenharmony_ci 598c2ecf20Sopenharmony_ci spinlock_t lock; /* protects the lists */ 608c2ecf20Sopenharmony_ci struct bio_list reads; 618c2ecf20Sopenharmony_ci struct bio_list writes; 628c2ecf20Sopenharmony_ci struct bio_list failures; 638c2ecf20Sopenharmony_ci struct bio_list holds; /* bios are waiting until suspend */ 648c2ecf20Sopenharmony_ci 658c2ecf20Sopenharmony_ci struct dm_region_hash *rh; 668c2ecf20Sopenharmony_ci struct dm_kcopyd_client *kcopyd_client; 678c2ecf20Sopenharmony_ci struct dm_io_client *io_client; 688c2ecf20Sopenharmony_ci 698c2ecf20Sopenharmony_ci /* recovery */ 708c2ecf20Sopenharmony_ci region_t nr_regions; 718c2ecf20Sopenharmony_ci int in_sync; 728c2ecf20Sopenharmony_ci int log_failure; 738c2ecf20Sopenharmony_ci int leg_failure; 748c2ecf20Sopenharmony_ci atomic_t suspend; 758c2ecf20Sopenharmony_ci 768c2ecf20Sopenharmony_ci atomic_t default_mirror; /* Default mirror */ 778c2ecf20Sopenharmony_ci 788c2ecf20Sopenharmony_ci struct workqueue_struct *kmirrord_wq; 798c2ecf20Sopenharmony_ci struct work_struct kmirrord_work; 808c2ecf20Sopenharmony_ci struct timer_list timer; 818c2ecf20Sopenharmony_ci unsigned long timer_pending; 828c2ecf20Sopenharmony_ci 838c2ecf20Sopenharmony_ci struct work_struct trigger_event; 848c2ecf20Sopenharmony_ci 858c2ecf20Sopenharmony_ci unsigned nr_mirrors; 868c2ecf20Sopenharmony_ci struct mirror mirror[]; 878c2ecf20Sopenharmony_ci}; 888c2ecf20Sopenharmony_ci 898c2ecf20Sopenharmony_ciDECLARE_DM_KCOPYD_THROTTLE_WITH_MODULE_PARM(raid1_resync_throttle, 908c2ecf20Sopenharmony_ci "A percentage of time allocated for raid resynchronization"); 918c2ecf20Sopenharmony_ci 928c2ecf20Sopenharmony_cistatic void wakeup_mirrord(void *context) 938c2ecf20Sopenharmony_ci{ 948c2ecf20Sopenharmony_ci struct mirror_set *ms = context; 958c2ecf20Sopenharmony_ci 968c2ecf20Sopenharmony_ci queue_work(ms->kmirrord_wq, &ms->kmirrord_work); 978c2ecf20Sopenharmony_ci} 988c2ecf20Sopenharmony_ci 998c2ecf20Sopenharmony_cistatic void delayed_wake_fn(struct timer_list *t) 1008c2ecf20Sopenharmony_ci{ 1018c2ecf20Sopenharmony_ci struct mirror_set *ms = from_timer(ms, t, timer); 1028c2ecf20Sopenharmony_ci 1038c2ecf20Sopenharmony_ci clear_bit(0, &ms->timer_pending); 1048c2ecf20Sopenharmony_ci wakeup_mirrord(ms); 1058c2ecf20Sopenharmony_ci} 1068c2ecf20Sopenharmony_ci 1078c2ecf20Sopenharmony_cistatic void delayed_wake(struct mirror_set *ms) 1088c2ecf20Sopenharmony_ci{ 1098c2ecf20Sopenharmony_ci if (test_and_set_bit(0, &ms->timer_pending)) 1108c2ecf20Sopenharmony_ci return; 1118c2ecf20Sopenharmony_ci 1128c2ecf20Sopenharmony_ci ms->timer.expires = jiffies + HZ / 5; 1138c2ecf20Sopenharmony_ci add_timer(&ms->timer); 1148c2ecf20Sopenharmony_ci} 1158c2ecf20Sopenharmony_ci 1168c2ecf20Sopenharmony_cistatic void wakeup_all_recovery_waiters(void *context) 1178c2ecf20Sopenharmony_ci{ 1188c2ecf20Sopenharmony_ci wake_up_all(&_kmirrord_recovery_stopped); 1198c2ecf20Sopenharmony_ci} 1208c2ecf20Sopenharmony_ci 1218c2ecf20Sopenharmony_cistatic void queue_bio(struct mirror_set *ms, struct bio *bio, int rw) 1228c2ecf20Sopenharmony_ci{ 1238c2ecf20Sopenharmony_ci unsigned long flags; 1248c2ecf20Sopenharmony_ci int should_wake = 0; 1258c2ecf20Sopenharmony_ci struct bio_list *bl; 1268c2ecf20Sopenharmony_ci 1278c2ecf20Sopenharmony_ci bl = (rw == WRITE) ? &ms->writes : &ms->reads; 1288c2ecf20Sopenharmony_ci spin_lock_irqsave(&ms->lock, flags); 1298c2ecf20Sopenharmony_ci should_wake = !(bl->head); 1308c2ecf20Sopenharmony_ci bio_list_add(bl, bio); 1318c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&ms->lock, flags); 1328c2ecf20Sopenharmony_ci 1338c2ecf20Sopenharmony_ci if (should_wake) 1348c2ecf20Sopenharmony_ci wakeup_mirrord(ms); 1358c2ecf20Sopenharmony_ci} 1368c2ecf20Sopenharmony_ci 1378c2ecf20Sopenharmony_cistatic void dispatch_bios(void *context, struct bio_list *bio_list) 1388c2ecf20Sopenharmony_ci{ 1398c2ecf20Sopenharmony_ci struct mirror_set *ms = context; 1408c2ecf20Sopenharmony_ci struct bio *bio; 1418c2ecf20Sopenharmony_ci 1428c2ecf20Sopenharmony_ci while ((bio = bio_list_pop(bio_list))) 1438c2ecf20Sopenharmony_ci queue_bio(ms, bio, WRITE); 1448c2ecf20Sopenharmony_ci} 1458c2ecf20Sopenharmony_ci 1468c2ecf20Sopenharmony_cistruct dm_raid1_bio_record { 1478c2ecf20Sopenharmony_ci struct mirror *m; 1488c2ecf20Sopenharmony_ci /* if details->bi_disk == NULL, details were not saved */ 1498c2ecf20Sopenharmony_ci struct dm_bio_details details; 1508c2ecf20Sopenharmony_ci region_t write_region; 1518c2ecf20Sopenharmony_ci}; 1528c2ecf20Sopenharmony_ci 1538c2ecf20Sopenharmony_ci/* 1548c2ecf20Sopenharmony_ci * Every mirror should look like this one. 1558c2ecf20Sopenharmony_ci */ 1568c2ecf20Sopenharmony_ci#define DEFAULT_MIRROR 0 1578c2ecf20Sopenharmony_ci 1588c2ecf20Sopenharmony_ci/* 1598c2ecf20Sopenharmony_ci * This is yucky. We squirrel the mirror struct away inside 1608c2ecf20Sopenharmony_ci * bi_next for read/write buffers. This is safe since the bh 1618c2ecf20Sopenharmony_ci * doesn't get submitted to the lower levels of block layer. 1628c2ecf20Sopenharmony_ci */ 1638c2ecf20Sopenharmony_cistatic struct mirror *bio_get_m(struct bio *bio) 1648c2ecf20Sopenharmony_ci{ 1658c2ecf20Sopenharmony_ci return (struct mirror *) bio->bi_next; 1668c2ecf20Sopenharmony_ci} 1678c2ecf20Sopenharmony_ci 1688c2ecf20Sopenharmony_cistatic void bio_set_m(struct bio *bio, struct mirror *m) 1698c2ecf20Sopenharmony_ci{ 1708c2ecf20Sopenharmony_ci bio->bi_next = (struct bio *) m; 1718c2ecf20Sopenharmony_ci} 1728c2ecf20Sopenharmony_ci 1738c2ecf20Sopenharmony_cistatic struct mirror *get_default_mirror(struct mirror_set *ms) 1748c2ecf20Sopenharmony_ci{ 1758c2ecf20Sopenharmony_ci return &ms->mirror[atomic_read(&ms->default_mirror)]; 1768c2ecf20Sopenharmony_ci} 1778c2ecf20Sopenharmony_ci 1788c2ecf20Sopenharmony_cistatic void set_default_mirror(struct mirror *m) 1798c2ecf20Sopenharmony_ci{ 1808c2ecf20Sopenharmony_ci struct mirror_set *ms = m->ms; 1818c2ecf20Sopenharmony_ci struct mirror *m0 = &(ms->mirror[0]); 1828c2ecf20Sopenharmony_ci 1838c2ecf20Sopenharmony_ci atomic_set(&ms->default_mirror, m - m0); 1848c2ecf20Sopenharmony_ci} 1858c2ecf20Sopenharmony_ci 1868c2ecf20Sopenharmony_cistatic struct mirror *get_valid_mirror(struct mirror_set *ms) 1878c2ecf20Sopenharmony_ci{ 1888c2ecf20Sopenharmony_ci struct mirror *m; 1898c2ecf20Sopenharmony_ci 1908c2ecf20Sopenharmony_ci for (m = ms->mirror; m < ms->mirror + ms->nr_mirrors; m++) 1918c2ecf20Sopenharmony_ci if (!atomic_read(&m->error_count)) 1928c2ecf20Sopenharmony_ci return m; 1938c2ecf20Sopenharmony_ci 1948c2ecf20Sopenharmony_ci return NULL; 1958c2ecf20Sopenharmony_ci} 1968c2ecf20Sopenharmony_ci 1978c2ecf20Sopenharmony_ci/* fail_mirror 1988c2ecf20Sopenharmony_ci * @m: mirror device to fail 1998c2ecf20Sopenharmony_ci * @error_type: one of the enum's, DM_RAID1_*_ERROR 2008c2ecf20Sopenharmony_ci * 2018c2ecf20Sopenharmony_ci * If errors are being handled, record the type of 2028c2ecf20Sopenharmony_ci * error encountered for this device. If this type 2038c2ecf20Sopenharmony_ci * of error has already been recorded, we can return; 2048c2ecf20Sopenharmony_ci * otherwise, we must signal userspace by triggering 2058c2ecf20Sopenharmony_ci * an event. Additionally, if the device is the 2068c2ecf20Sopenharmony_ci * primary device, we must choose a new primary, but 2078c2ecf20Sopenharmony_ci * only if the mirror is in-sync. 2088c2ecf20Sopenharmony_ci * 2098c2ecf20Sopenharmony_ci * This function must not block. 2108c2ecf20Sopenharmony_ci */ 2118c2ecf20Sopenharmony_cistatic void fail_mirror(struct mirror *m, enum dm_raid1_error error_type) 2128c2ecf20Sopenharmony_ci{ 2138c2ecf20Sopenharmony_ci struct mirror_set *ms = m->ms; 2148c2ecf20Sopenharmony_ci struct mirror *new; 2158c2ecf20Sopenharmony_ci 2168c2ecf20Sopenharmony_ci ms->leg_failure = 1; 2178c2ecf20Sopenharmony_ci 2188c2ecf20Sopenharmony_ci /* 2198c2ecf20Sopenharmony_ci * error_count is used for nothing more than a 2208c2ecf20Sopenharmony_ci * simple way to tell if a device has encountered 2218c2ecf20Sopenharmony_ci * errors. 2228c2ecf20Sopenharmony_ci */ 2238c2ecf20Sopenharmony_ci atomic_inc(&m->error_count); 2248c2ecf20Sopenharmony_ci 2258c2ecf20Sopenharmony_ci if (test_and_set_bit(error_type, &m->error_type)) 2268c2ecf20Sopenharmony_ci return; 2278c2ecf20Sopenharmony_ci 2288c2ecf20Sopenharmony_ci if (!errors_handled(ms)) 2298c2ecf20Sopenharmony_ci return; 2308c2ecf20Sopenharmony_ci 2318c2ecf20Sopenharmony_ci if (m != get_default_mirror(ms)) 2328c2ecf20Sopenharmony_ci goto out; 2338c2ecf20Sopenharmony_ci 2348c2ecf20Sopenharmony_ci if (!ms->in_sync && !keep_log(ms)) { 2358c2ecf20Sopenharmony_ci /* 2368c2ecf20Sopenharmony_ci * Better to issue requests to same failing device 2378c2ecf20Sopenharmony_ci * than to risk returning corrupt data. 2388c2ecf20Sopenharmony_ci */ 2398c2ecf20Sopenharmony_ci DMERR("Primary mirror (%s) failed while out-of-sync: " 2408c2ecf20Sopenharmony_ci "Reads may fail.", m->dev->name); 2418c2ecf20Sopenharmony_ci goto out; 2428c2ecf20Sopenharmony_ci } 2438c2ecf20Sopenharmony_ci 2448c2ecf20Sopenharmony_ci new = get_valid_mirror(ms); 2458c2ecf20Sopenharmony_ci if (new) 2468c2ecf20Sopenharmony_ci set_default_mirror(new); 2478c2ecf20Sopenharmony_ci else 2488c2ecf20Sopenharmony_ci DMWARN("All sides of mirror have failed."); 2498c2ecf20Sopenharmony_ci 2508c2ecf20Sopenharmony_ciout: 2518c2ecf20Sopenharmony_ci schedule_work(&ms->trigger_event); 2528c2ecf20Sopenharmony_ci} 2538c2ecf20Sopenharmony_ci 2548c2ecf20Sopenharmony_cistatic int mirror_flush(struct dm_target *ti) 2558c2ecf20Sopenharmony_ci{ 2568c2ecf20Sopenharmony_ci struct mirror_set *ms = ti->private; 2578c2ecf20Sopenharmony_ci unsigned long error_bits; 2588c2ecf20Sopenharmony_ci 2598c2ecf20Sopenharmony_ci unsigned int i; 2608c2ecf20Sopenharmony_ci struct dm_io_region io[MAX_NR_MIRRORS]; 2618c2ecf20Sopenharmony_ci struct mirror *m; 2628c2ecf20Sopenharmony_ci struct dm_io_request io_req = { 2638c2ecf20Sopenharmony_ci .bi_op = REQ_OP_WRITE, 2648c2ecf20Sopenharmony_ci .bi_op_flags = REQ_PREFLUSH | REQ_SYNC, 2658c2ecf20Sopenharmony_ci .mem.type = DM_IO_KMEM, 2668c2ecf20Sopenharmony_ci .mem.ptr.addr = NULL, 2678c2ecf20Sopenharmony_ci .client = ms->io_client, 2688c2ecf20Sopenharmony_ci }; 2698c2ecf20Sopenharmony_ci 2708c2ecf20Sopenharmony_ci for (i = 0, m = ms->mirror; i < ms->nr_mirrors; i++, m++) { 2718c2ecf20Sopenharmony_ci io[i].bdev = m->dev->bdev; 2728c2ecf20Sopenharmony_ci io[i].sector = 0; 2738c2ecf20Sopenharmony_ci io[i].count = 0; 2748c2ecf20Sopenharmony_ci } 2758c2ecf20Sopenharmony_ci 2768c2ecf20Sopenharmony_ci error_bits = -1; 2778c2ecf20Sopenharmony_ci dm_io(&io_req, ms->nr_mirrors, io, &error_bits); 2788c2ecf20Sopenharmony_ci if (unlikely(error_bits != 0)) { 2798c2ecf20Sopenharmony_ci for (i = 0; i < ms->nr_mirrors; i++) 2808c2ecf20Sopenharmony_ci if (test_bit(i, &error_bits)) 2818c2ecf20Sopenharmony_ci fail_mirror(ms->mirror + i, 2828c2ecf20Sopenharmony_ci DM_RAID1_FLUSH_ERROR); 2838c2ecf20Sopenharmony_ci return -EIO; 2848c2ecf20Sopenharmony_ci } 2858c2ecf20Sopenharmony_ci 2868c2ecf20Sopenharmony_ci return 0; 2878c2ecf20Sopenharmony_ci} 2888c2ecf20Sopenharmony_ci 2898c2ecf20Sopenharmony_ci/*----------------------------------------------------------------- 2908c2ecf20Sopenharmony_ci * Recovery. 2918c2ecf20Sopenharmony_ci * 2928c2ecf20Sopenharmony_ci * When a mirror is first activated we may find that some regions 2938c2ecf20Sopenharmony_ci * are in the no-sync state. We have to recover these by 2948c2ecf20Sopenharmony_ci * recopying from the default mirror to all the others. 2958c2ecf20Sopenharmony_ci *---------------------------------------------------------------*/ 2968c2ecf20Sopenharmony_cistatic void recovery_complete(int read_err, unsigned long write_err, 2978c2ecf20Sopenharmony_ci void *context) 2988c2ecf20Sopenharmony_ci{ 2998c2ecf20Sopenharmony_ci struct dm_region *reg = context; 3008c2ecf20Sopenharmony_ci struct mirror_set *ms = dm_rh_region_context(reg); 3018c2ecf20Sopenharmony_ci int m, bit = 0; 3028c2ecf20Sopenharmony_ci 3038c2ecf20Sopenharmony_ci if (read_err) { 3048c2ecf20Sopenharmony_ci /* Read error means the failure of default mirror. */ 3058c2ecf20Sopenharmony_ci DMERR_LIMIT("Unable to read primary mirror during recovery"); 3068c2ecf20Sopenharmony_ci fail_mirror(get_default_mirror(ms), DM_RAID1_SYNC_ERROR); 3078c2ecf20Sopenharmony_ci } 3088c2ecf20Sopenharmony_ci 3098c2ecf20Sopenharmony_ci if (write_err) { 3108c2ecf20Sopenharmony_ci DMERR_LIMIT("Write error during recovery (error = 0x%lx)", 3118c2ecf20Sopenharmony_ci write_err); 3128c2ecf20Sopenharmony_ci /* 3138c2ecf20Sopenharmony_ci * Bits correspond to devices (excluding default mirror). 3148c2ecf20Sopenharmony_ci * The default mirror cannot change during recovery. 3158c2ecf20Sopenharmony_ci */ 3168c2ecf20Sopenharmony_ci for (m = 0; m < ms->nr_mirrors; m++) { 3178c2ecf20Sopenharmony_ci if (&ms->mirror[m] == get_default_mirror(ms)) 3188c2ecf20Sopenharmony_ci continue; 3198c2ecf20Sopenharmony_ci if (test_bit(bit, &write_err)) 3208c2ecf20Sopenharmony_ci fail_mirror(ms->mirror + m, 3218c2ecf20Sopenharmony_ci DM_RAID1_SYNC_ERROR); 3228c2ecf20Sopenharmony_ci bit++; 3238c2ecf20Sopenharmony_ci } 3248c2ecf20Sopenharmony_ci } 3258c2ecf20Sopenharmony_ci 3268c2ecf20Sopenharmony_ci dm_rh_recovery_end(reg, !(read_err || write_err)); 3278c2ecf20Sopenharmony_ci} 3288c2ecf20Sopenharmony_ci 3298c2ecf20Sopenharmony_cistatic void recover(struct mirror_set *ms, struct dm_region *reg) 3308c2ecf20Sopenharmony_ci{ 3318c2ecf20Sopenharmony_ci unsigned i; 3328c2ecf20Sopenharmony_ci struct dm_io_region from, to[DM_KCOPYD_MAX_REGIONS], *dest; 3338c2ecf20Sopenharmony_ci struct mirror *m; 3348c2ecf20Sopenharmony_ci unsigned long flags = 0; 3358c2ecf20Sopenharmony_ci region_t key = dm_rh_get_region_key(reg); 3368c2ecf20Sopenharmony_ci sector_t region_size = dm_rh_get_region_size(ms->rh); 3378c2ecf20Sopenharmony_ci 3388c2ecf20Sopenharmony_ci /* fill in the source */ 3398c2ecf20Sopenharmony_ci m = get_default_mirror(ms); 3408c2ecf20Sopenharmony_ci from.bdev = m->dev->bdev; 3418c2ecf20Sopenharmony_ci from.sector = m->offset + dm_rh_region_to_sector(ms->rh, key); 3428c2ecf20Sopenharmony_ci if (key == (ms->nr_regions - 1)) { 3438c2ecf20Sopenharmony_ci /* 3448c2ecf20Sopenharmony_ci * The final region may be smaller than 3458c2ecf20Sopenharmony_ci * region_size. 3468c2ecf20Sopenharmony_ci */ 3478c2ecf20Sopenharmony_ci from.count = ms->ti->len & (region_size - 1); 3488c2ecf20Sopenharmony_ci if (!from.count) 3498c2ecf20Sopenharmony_ci from.count = region_size; 3508c2ecf20Sopenharmony_ci } else 3518c2ecf20Sopenharmony_ci from.count = region_size; 3528c2ecf20Sopenharmony_ci 3538c2ecf20Sopenharmony_ci /* fill in the destinations */ 3548c2ecf20Sopenharmony_ci for (i = 0, dest = to; i < ms->nr_mirrors; i++) { 3558c2ecf20Sopenharmony_ci if (&ms->mirror[i] == get_default_mirror(ms)) 3568c2ecf20Sopenharmony_ci continue; 3578c2ecf20Sopenharmony_ci 3588c2ecf20Sopenharmony_ci m = ms->mirror + i; 3598c2ecf20Sopenharmony_ci dest->bdev = m->dev->bdev; 3608c2ecf20Sopenharmony_ci dest->sector = m->offset + dm_rh_region_to_sector(ms->rh, key); 3618c2ecf20Sopenharmony_ci dest->count = from.count; 3628c2ecf20Sopenharmony_ci dest++; 3638c2ecf20Sopenharmony_ci } 3648c2ecf20Sopenharmony_ci 3658c2ecf20Sopenharmony_ci /* hand to kcopyd */ 3668c2ecf20Sopenharmony_ci if (!errors_handled(ms)) 3678c2ecf20Sopenharmony_ci set_bit(DM_KCOPYD_IGNORE_ERROR, &flags); 3688c2ecf20Sopenharmony_ci 3698c2ecf20Sopenharmony_ci dm_kcopyd_copy(ms->kcopyd_client, &from, ms->nr_mirrors - 1, to, 3708c2ecf20Sopenharmony_ci flags, recovery_complete, reg); 3718c2ecf20Sopenharmony_ci} 3728c2ecf20Sopenharmony_ci 3738c2ecf20Sopenharmony_cistatic void reset_ms_flags(struct mirror_set *ms) 3748c2ecf20Sopenharmony_ci{ 3758c2ecf20Sopenharmony_ci unsigned int m; 3768c2ecf20Sopenharmony_ci 3778c2ecf20Sopenharmony_ci ms->leg_failure = 0; 3788c2ecf20Sopenharmony_ci for (m = 0; m < ms->nr_mirrors; m++) { 3798c2ecf20Sopenharmony_ci atomic_set(&(ms->mirror[m].error_count), 0); 3808c2ecf20Sopenharmony_ci ms->mirror[m].error_type = 0; 3818c2ecf20Sopenharmony_ci } 3828c2ecf20Sopenharmony_ci} 3838c2ecf20Sopenharmony_ci 3848c2ecf20Sopenharmony_cistatic void do_recovery(struct mirror_set *ms) 3858c2ecf20Sopenharmony_ci{ 3868c2ecf20Sopenharmony_ci struct dm_region *reg; 3878c2ecf20Sopenharmony_ci struct dm_dirty_log *log = dm_rh_dirty_log(ms->rh); 3888c2ecf20Sopenharmony_ci 3898c2ecf20Sopenharmony_ci /* 3908c2ecf20Sopenharmony_ci * Start quiescing some regions. 3918c2ecf20Sopenharmony_ci */ 3928c2ecf20Sopenharmony_ci dm_rh_recovery_prepare(ms->rh); 3938c2ecf20Sopenharmony_ci 3948c2ecf20Sopenharmony_ci /* 3958c2ecf20Sopenharmony_ci * Copy any already quiesced regions. 3968c2ecf20Sopenharmony_ci */ 3978c2ecf20Sopenharmony_ci while ((reg = dm_rh_recovery_start(ms->rh))) 3988c2ecf20Sopenharmony_ci recover(ms, reg); 3998c2ecf20Sopenharmony_ci 4008c2ecf20Sopenharmony_ci /* 4018c2ecf20Sopenharmony_ci * Update the in sync flag. 4028c2ecf20Sopenharmony_ci */ 4038c2ecf20Sopenharmony_ci if (!ms->in_sync && 4048c2ecf20Sopenharmony_ci (log->type->get_sync_count(log) == ms->nr_regions)) { 4058c2ecf20Sopenharmony_ci /* the sync is complete */ 4068c2ecf20Sopenharmony_ci dm_table_event(ms->ti->table); 4078c2ecf20Sopenharmony_ci ms->in_sync = 1; 4088c2ecf20Sopenharmony_ci reset_ms_flags(ms); 4098c2ecf20Sopenharmony_ci } 4108c2ecf20Sopenharmony_ci} 4118c2ecf20Sopenharmony_ci 4128c2ecf20Sopenharmony_ci/*----------------------------------------------------------------- 4138c2ecf20Sopenharmony_ci * Reads 4148c2ecf20Sopenharmony_ci *---------------------------------------------------------------*/ 4158c2ecf20Sopenharmony_cistatic struct mirror *choose_mirror(struct mirror_set *ms, sector_t sector) 4168c2ecf20Sopenharmony_ci{ 4178c2ecf20Sopenharmony_ci struct mirror *m = get_default_mirror(ms); 4188c2ecf20Sopenharmony_ci 4198c2ecf20Sopenharmony_ci do { 4208c2ecf20Sopenharmony_ci if (likely(!atomic_read(&m->error_count))) 4218c2ecf20Sopenharmony_ci return m; 4228c2ecf20Sopenharmony_ci 4238c2ecf20Sopenharmony_ci if (m-- == ms->mirror) 4248c2ecf20Sopenharmony_ci m += ms->nr_mirrors; 4258c2ecf20Sopenharmony_ci } while (m != get_default_mirror(ms)); 4268c2ecf20Sopenharmony_ci 4278c2ecf20Sopenharmony_ci return NULL; 4288c2ecf20Sopenharmony_ci} 4298c2ecf20Sopenharmony_ci 4308c2ecf20Sopenharmony_cistatic int default_ok(struct mirror *m) 4318c2ecf20Sopenharmony_ci{ 4328c2ecf20Sopenharmony_ci struct mirror *default_mirror = get_default_mirror(m->ms); 4338c2ecf20Sopenharmony_ci 4348c2ecf20Sopenharmony_ci return !atomic_read(&default_mirror->error_count); 4358c2ecf20Sopenharmony_ci} 4368c2ecf20Sopenharmony_ci 4378c2ecf20Sopenharmony_cistatic int mirror_available(struct mirror_set *ms, struct bio *bio) 4388c2ecf20Sopenharmony_ci{ 4398c2ecf20Sopenharmony_ci struct dm_dirty_log *log = dm_rh_dirty_log(ms->rh); 4408c2ecf20Sopenharmony_ci region_t region = dm_rh_bio_to_region(ms->rh, bio); 4418c2ecf20Sopenharmony_ci 4428c2ecf20Sopenharmony_ci if (log->type->in_sync(log, region, 0)) 4438c2ecf20Sopenharmony_ci return choose_mirror(ms, bio->bi_iter.bi_sector) ? 1 : 0; 4448c2ecf20Sopenharmony_ci 4458c2ecf20Sopenharmony_ci return 0; 4468c2ecf20Sopenharmony_ci} 4478c2ecf20Sopenharmony_ci 4488c2ecf20Sopenharmony_ci/* 4498c2ecf20Sopenharmony_ci * remap a buffer to a particular mirror. 4508c2ecf20Sopenharmony_ci */ 4518c2ecf20Sopenharmony_cistatic sector_t map_sector(struct mirror *m, struct bio *bio) 4528c2ecf20Sopenharmony_ci{ 4538c2ecf20Sopenharmony_ci if (unlikely(!bio->bi_iter.bi_size)) 4548c2ecf20Sopenharmony_ci return 0; 4558c2ecf20Sopenharmony_ci return m->offset + dm_target_offset(m->ms->ti, bio->bi_iter.bi_sector); 4568c2ecf20Sopenharmony_ci} 4578c2ecf20Sopenharmony_ci 4588c2ecf20Sopenharmony_cistatic void map_bio(struct mirror *m, struct bio *bio) 4598c2ecf20Sopenharmony_ci{ 4608c2ecf20Sopenharmony_ci bio_set_dev(bio, m->dev->bdev); 4618c2ecf20Sopenharmony_ci bio->bi_iter.bi_sector = map_sector(m, bio); 4628c2ecf20Sopenharmony_ci} 4638c2ecf20Sopenharmony_ci 4648c2ecf20Sopenharmony_cistatic void map_region(struct dm_io_region *io, struct mirror *m, 4658c2ecf20Sopenharmony_ci struct bio *bio) 4668c2ecf20Sopenharmony_ci{ 4678c2ecf20Sopenharmony_ci io->bdev = m->dev->bdev; 4688c2ecf20Sopenharmony_ci io->sector = map_sector(m, bio); 4698c2ecf20Sopenharmony_ci io->count = bio_sectors(bio); 4708c2ecf20Sopenharmony_ci} 4718c2ecf20Sopenharmony_ci 4728c2ecf20Sopenharmony_cistatic void hold_bio(struct mirror_set *ms, struct bio *bio) 4738c2ecf20Sopenharmony_ci{ 4748c2ecf20Sopenharmony_ci /* 4758c2ecf20Sopenharmony_ci * Lock is required to avoid race condition during suspend 4768c2ecf20Sopenharmony_ci * process. 4778c2ecf20Sopenharmony_ci */ 4788c2ecf20Sopenharmony_ci spin_lock_irq(&ms->lock); 4798c2ecf20Sopenharmony_ci 4808c2ecf20Sopenharmony_ci if (atomic_read(&ms->suspend)) { 4818c2ecf20Sopenharmony_ci spin_unlock_irq(&ms->lock); 4828c2ecf20Sopenharmony_ci 4838c2ecf20Sopenharmony_ci /* 4848c2ecf20Sopenharmony_ci * If device is suspended, complete the bio. 4858c2ecf20Sopenharmony_ci */ 4868c2ecf20Sopenharmony_ci if (dm_noflush_suspending(ms->ti)) 4878c2ecf20Sopenharmony_ci bio->bi_status = BLK_STS_DM_REQUEUE; 4888c2ecf20Sopenharmony_ci else 4898c2ecf20Sopenharmony_ci bio->bi_status = BLK_STS_IOERR; 4908c2ecf20Sopenharmony_ci 4918c2ecf20Sopenharmony_ci bio_endio(bio); 4928c2ecf20Sopenharmony_ci return; 4938c2ecf20Sopenharmony_ci } 4948c2ecf20Sopenharmony_ci 4958c2ecf20Sopenharmony_ci /* 4968c2ecf20Sopenharmony_ci * Hold bio until the suspend is complete. 4978c2ecf20Sopenharmony_ci */ 4988c2ecf20Sopenharmony_ci bio_list_add(&ms->holds, bio); 4998c2ecf20Sopenharmony_ci spin_unlock_irq(&ms->lock); 5008c2ecf20Sopenharmony_ci} 5018c2ecf20Sopenharmony_ci 5028c2ecf20Sopenharmony_ci/*----------------------------------------------------------------- 5038c2ecf20Sopenharmony_ci * Reads 5048c2ecf20Sopenharmony_ci *---------------------------------------------------------------*/ 5058c2ecf20Sopenharmony_cistatic void read_callback(unsigned long error, void *context) 5068c2ecf20Sopenharmony_ci{ 5078c2ecf20Sopenharmony_ci struct bio *bio = context; 5088c2ecf20Sopenharmony_ci struct mirror *m; 5098c2ecf20Sopenharmony_ci 5108c2ecf20Sopenharmony_ci m = bio_get_m(bio); 5118c2ecf20Sopenharmony_ci bio_set_m(bio, NULL); 5128c2ecf20Sopenharmony_ci 5138c2ecf20Sopenharmony_ci if (likely(!error)) { 5148c2ecf20Sopenharmony_ci bio_endio(bio); 5158c2ecf20Sopenharmony_ci return; 5168c2ecf20Sopenharmony_ci } 5178c2ecf20Sopenharmony_ci 5188c2ecf20Sopenharmony_ci fail_mirror(m, DM_RAID1_READ_ERROR); 5198c2ecf20Sopenharmony_ci 5208c2ecf20Sopenharmony_ci if (likely(default_ok(m)) || mirror_available(m->ms, bio)) { 5218c2ecf20Sopenharmony_ci DMWARN_LIMIT("Read failure on mirror device %s. " 5228c2ecf20Sopenharmony_ci "Trying alternative device.", 5238c2ecf20Sopenharmony_ci m->dev->name); 5248c2ecf20Sopenharmony_ci queue_bio(m->ms, bio, bio_data_dir(bio)); 5258c2ecf20Sopenharmony_ci return; 5268c2ecf20Sopenharmony_ci } 5278c2ecf20Sopenharmony_ci 5288c2ecf20Sopenharmony_ci DMERR_LIMIT("Read failure on mirror device %s. Failing I/O.", 5298c2ecf20Sopenharmony_ci m->dev->name); 5308c2ecf20Sopenharmony_ci bio_io_error(bio); 5318c2ecf20Sopenharmony_ci} 5328c2ecf20Sopenharmony_ci 5338c2ecf20Sopenharmony_ci/* Asynchronous read. */ 5348c2ecf20Sopenharmony_cistatic void read_async_bio(struct mirror *m, struct bio *bio) 5358c2ecf20Sopenharmony_ci{ 5368c2ecf20Sopenharmony_ci struct dm_io_region io; 5378c2ecf20Sopenharmony_ci struct dm_io_request io_req = { 5388c2ecf20Sopenharmony_ci .bi_op = REQ_OP_READ, 5398c2ecf20Sopenharmony_ci .bi_op_flags = 0, 5408c2ecf20Sopenharmony_ci .mem.type = DM_IO_BIO, 5418c2ecf20Sopenharmony_ci .mem.ptr.bio = bio, 5428c2ecf20Sopenharmony_ci .notify.fn = read_callback, 5438c2ecf20Sopenharmony_ci .notify.context = bio, 5448c2ecf20Sopenharmony_ci .client = m->ms->io_client, 5458c2ecf20Sopenharmony_ci }; 5468c2ecf20Sopenharmony_ci 5478c2ecf20Sopenharmony_ci map_region(&io, m, bio); 5488c2ecf20Sopenharmony_ci bio_set_m(bio, m); 5498c2ecf20Sopenharmony_ci BUG_ON(dm_io(&io_req, 1, &io, NULL)); 5508c2ecf20Sopenharmony_ci} 5518c2ecf20Sopenharmony_ci 5528c2ecf20Sopenharmony_cistatic inline int region_in_sync(struct mirror_set *ms, region_t region, 5538c2ecf20Sopenharmony_ci int may_block) 5548c2ecf20Sopenharmony_ci{ 5558c2ecf20Sopenharmony_ci int state = dm_rh_get_state(ms->rh, region, may_block); 5568c2ecf20Sopenharmony_ci return state == DM_RH_CLEAN || state == DM_RH_DIRTY; 5578c2ecf20Sopenharmony_ci} 5588c2ecf20Sopenharmony_ci 5598c2ecf20Sopenharmony_cistatic void do_reads(struct mirror_set *ms, struct bio_list *reads) 5608c2ecf20Sopenharmony_ci{ 5618c2ecf20Sopenharmony_ci region_t region; 5628c2ecf20Sopenharmony_ci struct bio *bio; 5638c2ecf20Sopenharmony_ci struct mirror *m; 5648c2ecf20Sopenharmony_ci 5658c2ecf20Sopenharmony_ci while ((bio = bio_list_pop(reads))) { 5668c2ecf20Sopenharmony_ci region = dm_rh_bio_to_region(ms->rh, bio); 5678c2ecf20Sopenharmony_ci m = get_default_mirror(ms); 5688c2ecf20Sopenharmony_ci 5698c2ecf20Sopenharmony_ci /* 5708c2ecf20Sopenharmony_ci * We can only read balance if the region is in sync. 5718c2ecf20Sopenharmony_ci */ 5728c2ecf20Sopenharmony_ci if (likely(region_in_sync(ms, region, 1))) 5738c2ecf20Sopenharmony_ci m = choose_mirror(ms, bio->bi_iter.bi_sector); 5748c2ecf20Sopenharmony_ci else if (m && atomic_read(&m->error_count)) 5758c2ecf20Sopenharmony_ci m = NULL; 5768c2ecf20Sopenharmony_ci 5778c2ecf20Sopenharmony_ci if (likely(m)) 5788c2ecf20Sopenharmony_ci read_async_bio(m, bio); 5798c2ecf20Sopenharmony_ci else 5808c2ecf20Sopenharmony_ci bio_io_error(bio); 5818c2ecf20Sopenharmony_ci } 5828c2ecf20Sopenharmony_ci} 5838c2ecf20Sopenharmony_ci 5848c2ecf20Sopenharmony_ci/*----------------------------------------------------------------- 5858c2ecf20Sopenharmony_ci * Writes. 5868c2ecf20Sopenharmony_ci * 5878c2ecf20Sopenharmony_ci * We do different things with the write io depending on the 5888c2ecf20Sopenharmony_ci * state of the region that it's in: 5898c2ecf20Sopenharmony_ci * 5908c2ecf20Sopenharmony_ci * SYNC: increment pending, use kcopyd to write to *all* mirrors 5918c2ecf20Sopenharmony_ci * RECOVERING: delay the io until recovery completes 5928c2ecf20Sopenharmony_ci * NOSYNC: increment pending, just write to the default mirror 5938c2ecf20Sopenharmony_ci *---------------------------------------------------------------*/ 5948c2ecf20Sopenharmony_ci 5958c2ecf20Sopenharmony_ci 5968c2ecf20Sopenharmony_cistatic void write_callback(unsigned long error, void *context) 5978c2ecf20Sopenharmony_ci{ 5988c2ecf20Sopenharmony_ci unsigned i; 5998c2ecf20Sopenharmony_ci struct bio *bio = (struct bio *) context; 6008c2ecf20Sopenharmony_ci struct mirror_set *ms; 6018c2ecf20Sopenharmony_ci int should_wake = 0; 6028c2ecf20Sopenharmony_ci unsigned long flags; 6038c2ecf20Sopenharmony_ci 6048c2ecf20Sopenharmony_ci ms = bio_get_m(bio)->ms; 6058c2ecf20Sopenharmony_ci bio_set_m(bio, NULL); 6068c2ecf20Sopenharmony_ci 6078c2ecf20Sopenharmony_ci /* 6088c2ecf20Sopenharmony_ci * NOTE: We don't decrement the pending count here, 6098c2ecf20Sopenharmony_ci * instead it is done by the targets endio function. 6108c2ecf20Sopenharmony_ci * This way we handle both writes to SYNC and NOSYNC 6118c2ecf20Sopenharmony_ci * regions with the same code. 6128c2ecf20Sopenharmony_ci */ 6138c2ecf20Sopenharmony_ci if (likely(!error)) { 6148c2ecf20Sopenharmony_ci bio_endio(bio); 6158c2ecf20Sopenharmony_ci return; 6168c2ecf20Sopenharmony_ci } 6178c2ecf20Sopenharmony_ci 6188c2ecf20Sopenharmony_ci /* 6198c2ecf20Sopenharmony_ci * If the bio is discard, return an error, but do not 6208c2ecf20Sopenharmony_ci * degrade the array. 6218c2ecf20Sopenharmony_ci */ 6228c2ecf20Sopenharmony_ci if (bio_op(bio) == REQ_OP_DISCARD) { 6238c2ecf20Sopenharmony_ci bio->bi_status = BLK_STS_NOTSUPP; 6248c2ecf20Sopenharmony_ci bio_endio(bio); 6258c2ecf20Sopenharmony_ci return; 6268c2ecf20Sopenharmony_ci } 6278c2ecf20Sopenharmony_ci 6288c2ecf20Sopenharmony_ci for (i = 0; i < ms->nr_mirrors; i++) 6298c2ecf20Sopenharmony_ci if (test_bit(i, &error)) 6308c2ecf20Sopenharmony_ci fail_mirror(ms->mirror + i, DM_RAID1_WRITE_ERROR); 6318c2ecf20Sopenharmony_ci 6328c2ecf20Sopenharmony_ci /* 6338c2ecf20Sopenharmony_ci * Need to raise event. Since raising 6348c2ecf20Sopenharmony_ci * events can block, we need to do it in 6358c2ecf20Sopenharmony_ci * the main thread. 6368c2ecf20Sopenharmony_ci */ 6378c2ecf20Sopenharmony_ci spin_lock_irqsave(&ms->lock, flags); 6388c2ecf20Sopenharmony_ci if (!ms->failures.head) 6398c2ecf20Sopenharmony_ci should_wake = 1; 6408c2ecf20Sopenharmony_ci bio_list_add(&ms->failures, bio); 6418c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&ms->lock, flags); 6428c2ecf20Sopenharmony_ci if (should_wake) 6438c2ecf20Sopenharmony_ci wakeup_mirrord(ms); 6448c2ecf20Sopenharmony_ci} 6458c2ecf20Sopenharmony_ci 6468c2ecf20Sopenharmony_cistatic void do_write(struct mirror_set *ms, struct bio *bio) 6478c2ecf20Sopenharmony_ci{ 6488c2ecf20Sopenharmony_ci unsigned int i; 6498c2ecf20Sopenharmony_ci struct dm_io_region io[MAX_NR_MIRRORS], *dest = io; 6508c2ecf20Sopenharmony_ci struct mirror *m; 6518c2ecf20Sopenharmony_ci struct dm_io_request io_req = { 6528c2ecf20Sopenharmony_ci .bi_op = REQ_OP_WRITE, 6538c2ecf20Sopenharmony_ci .bi_op_flags = bio->bi_opf & (REQ_FUA | REQ_PREFLUSH), 6548c2ecf20Sopenharmony_ci .mem.type = DM_IO_BIO, 6558c2ecf20Sopenharmony_ci .mem.ptr.bio = bio, 6568c2ecf20Sopenharmony_ci .notify.fn = write_callback, 6578c2ecf20Sopenharmony_ci .notify.context = bio, 6588c2ecf20Sopenharmony_ci .client = ms->io_client, 6598c2ecf20Sopenharmony_ci }; 6608c2ecf20Sopenharmony_ci 6618c2ecf20Sopenharmony_ci if (bio_op(bio) == REQ_OP_DISCARD) { 6628c2ecf20Sopenharmony_ci io_req.bi_op = REQ_OP_DISCARD; 6638c2ecf20Sopenharmony_ci io_req.mem.type = DM_IO_KMEM; 6648c2ecf20Sopenharmony_ci io_req.mem.ptr.addr = NULL; 6658c2ecf20Sopenharmony_ci } 6668c2ecf20Sopenharmony_ci 6678c2ecf20Sopenharmony_ci for (i = 0, m = ms->mirror; i < ms->nr_mirrors; i++, m++) 6688c2ecf20Sopenharmony_ci map_region(dest++, m, bio); 6698c2ecf20Sopenharmony_ci 6708c2ecf20Sopenharmony_ci /* 6718c2ecf20Sopenharmony_ci * Use default mirror because we only need it to retrieve the reference 6728c2ecf20Sopenharmony_ci * to the mirror set in write_callback(). 6738c2ecf20Sopenharmony_ci */ 6748c2ecf20Sopenharmony_ci bio_set_m(bio, get_default_mirror(ms)); 6758c2ecf20Sopenharmony_ci 6768c2ecf20Sopenharmony_ci BUG_ON(dm_io(&io_req, ms->nr_mirrors, io, NULL)); 6778c2ecf20Sopenharmony_ci} 6788c2ecf20Sopenharmony_ci 6798c2ecf20Sopenharmony_cistatic void do_writes(struct mirror_set *ms, struct bio_list *writes) 6808c2ecf20Sopenharmony_ci{ 6818c2ecf20Sopenharmony_ci int state; 6828c2ecf20Sopenharmony_ci struct bio *bio; 6838c2ecf20Sopenharmony_ci struct bio_list sync, nosync, recover, *this_list = NULL; 6848c2ecf20Sopenharmony_ci struct bio_list requeue; 6858c2ecf20Sopenharmony_ci struct dm_dirty_log *log = dm_rh_dirty_log(ms->rh); 6868c2ecf20Sopenharmony_ci region_t region; 6878c2ecf20Sopenharmony_ci 6888c2ecf20Sopenharmony_ci if (!writes->head) 6898c2ecf20Sopenharmony_ci return; 6908c2ecf20Sopenharmony_ci 6918c2ecf20Sopenharmony_ci /* 6928c2ecf20Sopenharmony_ci * Classify each write. 6938c2ecf20Sopenharmony_ci */ 6948c2ecf20Sopenharmony_ci bio_list_init(&sync); 6958c2ecf20Sopenharmony_ci bio_list_init(&nosync); 6968c2ecf20Sopenharmony_ci bio_list_init(&recover); 6978c2ecf20Sopenharmony_ci bio_list_init(&requeue); 6988c2ecf20Sopenharmony_ci 6998c2ecf20Sopenharmony_ci while ((bio = bio_list_pop(writes))) { 7008c2ecf20Sopenharmony_ci if ((bio->bi_opf & REQ_PREFLUSH) || 7018c2ecf20Sopenharmony_ci (bio_op(bio) == REQ_OP_DISCARD)) { 7028c2ecf20Sopenharmony_ci bio_list_add(&sync, bio); 7038c2ecf20Sopenharmony_ci continue; 7048c2ecf20Sopenharmony_ci } 7058c2ecf20Sopenharmony_ci 7068c2ecf20Sopenharmony_ci region = dm_rh_bio_to_region(ms->rh, bio); 7078c2ecf20Sopenharmony_ci 7088c2ecf20Sopenharmony_ci if (log->type->is_remote_recovering && 7098c2ecf20Sopenharmony_ci log->type->is_remote_recovering(log, region)) { 7108c2ecf20Sopenharmony_ci bio_list_add(&requeue, bio); 7118c2ecf20Sopenharmony_ci continue; 7128c2ecf20Sopenharmony_ci } 7138c2ecf20Sopenharmony_ci 7148c2ecf20Sopenharmony_ci state = dm_rh_get_state(ms->rh, region, 1); 7158c2ecf20Sopenharmony_ci switch (state) { 7168c2ecf20Sopenharmony_ci case DM_RH_CLEAN: 7178c2ecf20Sopenharmony_ci case DM_RH_DIRTY: 7188c2ecf20Sopenharmony_ci this_list = &sync; 7198c2ecf20Sopenharmony_ci break; 7208c2ecf20Sopenharmony_ci 7218c2ecf20Sopenharmony_ci case DM_RH_NOSYNC: 7228c2ecf20Sopenharmony_ci this_list = &nosync; 7238c2ecf20Sopenharmony_ci break; 7248c2ecf20Sopenharmony_ci 7258c2ecf20Sopenharmony_ci case DM_RH_RECOVERING: 7268c2ecf20Sopenharmony_ci this_list = &recover; 7278c2ecf20Sopenharmony_ci break; 7288c2ecf20Sopenharmony_ci } 7298c2ecf20Sopenharmony_ci 7308c2ecf20Sopenharmony_ci bio_list_add(this_list, bio); 7318c2ecf20Sopenharmony_ci } 7328c2ecf20Sopenharmony_ci 7338c2ecf20Sopenharmony_ci /* 7348c2ecf20Sopenharmony_ci * Add bios that are delayed due to remote recovery 7358c2ecf20Sopenharmony_ci * back on to the write queue 7368c2ecf20Sopenharmony_ci */ 7378c2ecf20Sopenharmony_ci if (unlikely(requeue.head)) { 7388c2ecf20Sopenharmony_ci spin_lock_irq(&ms->lock); 7398c2ecf20Sopenharmony_ci bio_list_merge(&ms->writes, &requeue); 7408c2ecf20Sopenharmony_ci spin_unlock_irq(&ms->lock); 7418c2ecf20Sopenharmony_ci delayed_wake(ms); 7428c2ecf20Sopenharmony_ci } 7438c2ecf20Sopenharmony_ci 7448c2ecf20Sopenharmony_ci /* 7458c2ecf20Sopenharmony_ci * Increment the pending counts for any regions that will 7468c2ecf20Sopenharmony_ci * be written to (writes to recover regions are going to 7478c2ecf20Sopenharmony_ci * be delayed). 7488c2ecf20Sopenharmony_ci */ 7498c2ecf20Sopenharmony_ci dm_rh_inc_pending(ms->rh, &sync); 7508c2ecf20Sopenharmony_ci dm_rh_inc_pending(ms->rh, &nosync); 7518c2ecf20Sopenharmony_ci 7528c2ecf20Sopenharmony_ci /* 7538c2ecf20Sopenharmony_ci * If the flush fails on a previous call and succeeds here, 7548c2ecf20Sopenharmony_ci * we must not reset the log_failure variable. We need 7558c2ecf20Sopenharmony_ci * userspace interaction to do that. 7568c2ecf20Sopenharmony_ci */ 7578c2ecf20Sopenharmony_ci ms->log_failure = dm_rh_flush(ms->rh) ? 1 : ms->log_failure; 7588c2ecf20Sopenharmony_ci 7598c2ecf20Sopenharmony_ci /* 7608c2ecf20Sopenharmony_ci * Dispatch io. 7618c2ecf20Sopenharmony_ci */ 7628c2ecf20Sopenharmony_ci if (unlikely(ms->log_failure) && errors_handled(ms)) { 7638c2ecf20Sopenharmony_ci spin_lock_irq(&ms->lock); 7648c2ecf20Sopenharmony_ci bio_list_merge(&ms->failures, &sync); 7658c2ecf20Sopenharmony_ci spin_unlock_irq(&ms->lock); 7668c2ecf20Sopenharmony_ci wakeup_mirrord(ms); 7678c2ecf20Sopenharmony_ci } else 7688c2ecf20Sopenharmony_ci while ((bio = bio_list_pop(&sync))) 7698c2ecf20Sopenharmony_ci do_write(ms, bio); 7708c2ecf20Sopenharmony_ci 7718c2ecf20Sopenharmony_ci while ((bio = bio_list_pop(&recover))) 7728c2ecf20Sopenharmony_ci dm_rh_delay(ms->rh, bio); 7738c2ecf20Sopenharmony_ci 7748c2ecf20Sopenharmony_ci while ((bio = bio_list_pop(&nosync))) { 7758c2ecf20Sopenharmony_ci if (unlikely(ms->leg_failure) && errors_handled(ms) && !keep_log(ms)) { 7768c2ecf20Sopenharmony_ci spin_lock_irq(&ms->lock); 7778c2ecf20Sopenharmony_ci bio_list_add(&ms->failures, bio); 7788c2ecf20Sopenharmony_ci spin_unlock_irq(&ms->lock); 7798c2ecf20Sopenharmony_ci wakeup_mirrord(ms); 7808c2ecf20Sopenharmony_ci } else { 7818c2ecf20Sopenharmony_ci map_bio(get_default_mirror(ms), bio); 7828c2ecf20Sopenharmony_ci submit_bio_noacct(bio); 7838c2ecf20Sopenharmony_ci } 7848c2ecf20Sopenharmony_ci } 7858c2ecf20Sopenharmony_ci} 7868c2ecf20Sopenharmony_ci 7878c2ecf20Sopenharmony_cistatic void do_failures(struct mirror_set *ms, struct bio_list *failures) 7888c2ecf20Sopenharmony_ci{ 7898c2ecf20Sopenharmony_ci struct bio *bio; 7908c2ecf20Sopenharmony_ci 7918c2ecf20Sopenharmony_ci if (likely(!failures->head)) 7928c2ecf20Sopenharmony_ci return; 7938c2ecf20Sopenharmony_ci 7948c2ecf20Sopenharmony_ci /* 7958c2ecf20Sopenharmony_ci * If the log has failed, unattempted writes are being 7968c2ecf20Sopenharmony_ci * put on the holds list. We can't issue those writes 7978c2ecf20Sopenharmony_ci * until a log has been marked, so we must store them. 7988c2ecf20Sopenharmony_ci * 7998c2ecf20Sopenharmony_ci * If a 'noflush' suspend is in progress, we can requeue 8008c2ecf20Sopenharmony_ci * the I/O's to the core. This give userspace a chance 8018c2ecf20Sopenharmony_ci * to reconfigure the mirror, at which point the core 8028c2ecf20Sopenharmony_ci * will reissue the writes. If the 'noflush' flag is 8038c2ecf20Sopenharmony_ci * not set, we have no choice but to return errors. 8048c2ecf20Sopenharmony_ci * 8058c2ecf20Sopenharmony_ci * Some writes on the failures list may have been 8068c2ecf20Sopenharmony_ci * submitted before the log failure and represent a 8078c2ecf20Sopenharmony_ci * failure to write to one of the devices. It is ok 8088c2ecf20Sopenharmony_ci * for us to treat them the same and requeue them 8098c2ecf20Sopenharmony_ci * as well. 8108c2ecf20Sopenharmony_ci */ 8118c2ecf20Sopenharmony_ci while ((bio = bio_list_pop(failures))) { 8128c2ecf20Sopenharmony_ci if (!ms->log_failure) { 8138c2ecf20Sopenharmony_ci ms->in_sync = 0; 8148c2ecf20Sopenharmony_ci dm_rh_mark_nosync(ms->rh, bio); 8158c2ecf20Sopenharmony_ci } 8168c2ecf20Sopenharmony_ci 8178c2ecf20Sopenharmony_ci /* 8188c2ecf20Sopenharmony_ci * If all the legs are dead, fail the I/O. 8198c2ecf20Sopenharmony_ci * If the device has failed and keep_log is enabled, 8208c2ecf20Sopenharmony_ci * fail the I/O. 8218c2ecf20Sopenharmony_ci * 8228c2ecf20Sopenharmony_ci * If we have been told to handle errors, and keep_log 8238c2ecf20Sopenharmony_ci * isn't enabled, hold the bio and wait for userspace to 8248c2ecf20Sopenharmony_ci * deal with the problem. 8258c2ecf20Sopenharmony_ci * 8268c2ecf20Sopenharmony_ci * Otherwise pretend that the I/O succeeded. (This would 8278c2ecf20Sopenharmony_ci * be wrong if the failed leg returned after reboot and 8288c2ecf20Sopenharmony_ci * got replicated back to the good legs.) 8298c2ecf20Sopenharmony_ci */ 8308c2ecf20Sopenharmony_ci if (unlikely(!get_valid_mirror(ms) || (keep_log(ms) && ms->log_failure))) 8318c2ecf20Sopenharmony_ci bio_io_error(bio); 8328c2ecf20Sopenharmony_ci else if (errors_handled(ms) && !keep_log(ms)) 8338c2ecf20Sopenharmony_ci hold_bio(ms, bio); 8348c2ecf20Sopenharmony_ci else 8358c2ecf20Sopenharmony_ci bio_endio(bio); 8368c2ecf20Sopenharmony_ci } 8378c2ecf20Sopenharmony_ci} 8388c2ecf20Sopenharmony_ci 8398c2ecf20Sopenharmony_cistatic void trigger_event(struct work_struct *work) 8408c2ecf20Sopenharmony_ci{ 8418c2ecf20Sopenharmony_ci struct mirror_set *ms = 8428c2ecf20Sopenharmony_ci container_of(work, struct mirror_set, trigger_event); 8438c2ecf20Sopenharmony_ci 8448c2ecf20Sopenharmony_ci dm_table_event(ms->ti->table); 8458c2ecf20Sopenharmony_ci} 8468c2ecf20Sopenharmony_ci 8478c2ecf20Sopenharmony_ci/*----------------------------------------------------------------- 8488c2ecf20Sopenharmony_ci * kmirrord 8498c2ecf20Sopenharmony_ci *---------------------------------------------------------------*/ 8508c2ecf20Sopenharmony_cistatic void do_mirror(struct work_struct *work) 8518c2ecf20Sopenharmony_ci{ 8528c2ecf20Sopenharmony_ci struct mirror_set *ms = container_of(work, struct mirror_set, 8538c2ecf20Sopenharmony_ci kmirrord_work); 8548c2ecf20Sopenharmony_ci struct bio_list reads, writes, failures; 8558c2ecf20Sopenharmony_ci unsigned long flags; 8568c2ecf20Sopenharmony_ci 8578c2ecf20Sopenharmony_ci spin_lock_irqsave(&ms->lock, flags); 8588c2ecf20Sopenharmony_ci reads = ms->reads; 8598c2ecf20Sopenharmony_ci writes = ms->writes; 8608c2ecf20Sopenharmony_ci failures = ms->failures; 8618c2ecf20Sopenharmony_ci bio_list_init(&ms->reads); 8628c2ecf20Sopenharmony_ci bio_list_init(&ms->writes); 8638c2ecf20Sopenharmony_ci bio_list_init(&ms->failures); 8648c2ecf20Sopenharmony_ci spin_unlock_irqrestore(&ms->lock, flags); 8658c2ecf20Sopenharmony_ci 8668c2ecf20Sopenharmony_ci dm_rh_update_states(ms->rh, errors_handled(ms)); 8678c2ecf20Sopenharmony_ci do_recovery(ms); 8688c2ecf20Sopenharmony_ci do_reads(ms, &reads); 8698c2ecf20Sopenharmony_ci do_writes(ms, &writes); 8708c2ecf20Sopenharmony_ci do_failures(ms, &failures); 8718c2ecf20Sopenharmony_ci} 8728c2ecf20Sopenharmony_ci 8738c2ecf20Sopenharmony_ci/*----------------------------------------------------------------- 8748c2ecf20Sopenharmony_ci * Target functions 8758c2ecf20Sopenharmony_ci *---------------------------------------------------------------*/ 8768c2ecf20Sopenharmony_cistatic struct mirror_set *alloc_context(unsigned int nr_mirrors, 8778c2ecf20Sopenharmony_ci uint32_t region_size, 8788c2ecf20Sopenharmony_ci struct dm_target *ti, 8798c2ecf20Sopenharmony_ci struct dm_dirty_log *dl) 8808c2ecf20Sopenharmony_ci{ 8818c2ecf20Sopenharmony_ci struct mirror_set *ms = 8828c2ecf20Sopenharmony_ci kzalloc(struct_size(ms, mirror, nr_mirrors), GFP_KERNEL); 8838c2ecf20Sopenharmony_ci 8848c2ecf20Sopenharmony_ci if (!ms) { 8858c2ecf20Sopenharmony_ci ti->error = "Cannot allocate mirror context"; 8868c2ecf20Sopenharmony_ci return NULL; 8878c2ecf20Sopenharmony_ci } 8888c2ecf20Sopenharmony_ci 8898c2ecf20Sopenharmony_ci spin_lock_init(&ms->lock); 8908c2ecf20Sopenharmony_ci bio_list_init(&ms->reads); 8918c2ecf20Sopenharmony_ci bio_list_init(&ms->writes); 8928c2ecf20Sopenharmony_ci bio_list_init(&ms->failures); 8938c2ecf20Sopenharmony_ci bio_list_init(&ms->holds); 8948c2ecf20Sopenharmony_ci 8958c2ecf20Sopenharmony_ci ms->ti = ti; 8968c2ecf20Sopenharmony_ci ms->nr_mirrors = nr_mirrors; 8978c2ecf20Sopenharmony_ci ms->nr_regions = dm_sector_div_up(ti->len, region_size); 8988c2ecf20Sopenharmony_ci ms->in_sync = 0; 8998c2ecf20Sopenharmony_ci ms->log_failure = 0; 9008c2ecf20Sopenharmony_ci ms->leg_failure = 0; 9018c2ecf20Sopenharmony_ci atomic_set(&ms->suspend, 0); 9028c2ecf20Sopenharmony_ci atomic_set(&ms->default_mirror, DEFAULT_MIRROR); 9038c2ecf20Sopenharmony_ci 9048c2ecf20Sopenharmony_ci ms->io_client = dm_io_client_create(); 9058c2ecf20Sopenharmony_ci if (IS_ERR(ms->io_client)) { 9068c2ecf20Sopenharmony_ci ti->error = "Error creating dm_io client"; 9078c2ecf20Sopenharmony_ci kfree(ms); 9088c2ecf20Sopenharmony_ci return NULL; 9098c2ecf20Sopenharmony_ci } 9108c2ecf20Sopenharmony_ci 9118c2ecf20Sopenharmony_ci ms->rh = dm_region_hash_create(ms, dispatch_bios, wakeup_mirrord, 9128c2ecf20Sopenharmony_ci wakeup_all_recovery_waiters, 9138c2ecf20Sopenharmony_ci ms->ti->begin, MAX_RECOVERY, 9148c2ecf20Sopenharmony_ci dl, region_size, ms->nr_regions); 9158c2ecf20Sopenharmony_ci if (IS_ERR(ms->rh)) { 9168c2ecf20Sopenharmony_ci ti->error = "Error creating dirty region hash"; 9178c2ecf20Sopenharmony_ci dm_io_client_destroy(ms->io_client); 9188c2ecf20Sopenharmony_ci kfree(ms); 9198c2ecf20Sopenharmony_ci return NULL; 9208c2ecf20Sopenharmony_ci } 9218c2ecf20Sopenharmony_ci 9228c2ecf20Sopenharmony_ci return ms; 9238c2ecf20Sopenharmony_ci} 9248c2ecf20Sopenharmony_ci 9258c2ecf20Sopenharmony_cistatic void free_context(struct mirror_set *ms, struct dm_target *ti, 9268c2ecf20Sopenharmony_ci unsigned int m) 9278c2ecf20Sopenharmony_ci{ 9288c2ecf20Sopenharmony_ci while (m--) 9298c2ecf20Sopenharmony_ci dm_put_device(ti, ms->mirror[m].dev); 9308c2ecf20Sopenharmony_ci 9318c2ecf20Sopenharmony_ci dm_io_client_destroy(ms->io_client); 9328c2ecf20Sopenharmony_ci dm_region_hash_destroy(ms->rh); 9338c2ecf20Sopenharmony_ci kfree(ms); 9348c2ecf20Sopenharmony_ci} 9358c2ecf20Sopenharmony_ci 9368c2ecf20Sopenharmony_cistatic int get_mirror(struct mirror_set *ms, struct dm_target *ti, 9378c2ecf20Sopenharmony_ci unsigned int mirror, char **argv) 9388c2ecf20Sopenharmony_ci{ 9398c2ecf20Sopenharmony_ci unsigned long long offset; 9408c2ecf20Sopenharmony_ci char dummy; 9418c2ecf20Sopenharmony_ci int ret; 9428c2ecf20Sopenharmony_ci 9438c2ecf20Sopenharmony_ci if (sscanf(argv[1], "%llu%c", &offset, &dummy) != 1 || 9448c2ecf20Sopenharmony_ci offset != (sector_t)offset) { 9458c2ecf20Sopenharmony_ci ti->error = "Invalid offset"; 9468c2ecf20Sopenharmony_ci return -EINVAL; 9478c2ecf20Sopenharmony_ci } 9488c2ecf20Sopenharmony_ci 9498c2ecf20Sopenharmony_ci ret = dm_get_device(ti, argv[0], dm_table_get_mode(ti->table), 9508c2ecf20Sopenharmony_ci &ms->mirror[mirror].dev); 9518c2ecf20Sopenharmony_ci if (ret) { 9528c2ecf20Sopenharmony_ci ti->error = "Device lookup failure"; 9538c2ecf20Sopenharmony_ci return ret; 9548c2ecf20Sopenharmony_ci } 9558c2ecf20Sopenharmony_ci 9568c2ecf20Sopenharmony_ci ms->mirror[mirror].ms = ms; 9578c2ecf20Sopenharmony_ci atomic_set(&(ms->mirror[mirror].error_count), 0); 9588c2ecf20Sopenharmony_ci ms->mirror[mirror].error_type = 0; 9598c2ecf20Sopenharmony_ci ms->mirror[mirror].offset = offset; 9608c2ecf20Sopenharmony_ci 9618c2ecf20Sopenharmony_ci return 0; 9628c2ecf20Sopenharmony_ci} 9638c2ecf20Sopenharmony_ci 9648c2ecf20Sopenharmony_ci/* 9658c2ecf20Sopenharmony_ci * Create dirty log: log_type #log_params <log_params> 9668c2ecf20Sopenharmony_ci */ 9678c2ecf20Sopenharmony_cistatic struct dm_dirty_log *create_dirty_log(struct dm_target *ti, 9688c2ecf20Sopenharmony_ci unsigned argc, char **argv, 9698c2ecf20Sopenharmony_ci unsigned *args_used) 9708c2ecf20Sopenharmony_ci{ 9718c2ecf20Sopenharmony_ci unsigned param_count; 9728c2ecf20Sopenharmony_ci struct dm_dirty_log *dl; 9738c2ecf20Sopenharmony_ci char dummy; 9748c2ecf20Sopenharmony_ci 9758c2ecf20Sopenharmony_ci if (argc < 2) { 9768c2ecf20Sopenharmony_ci ti->error = "Insufficient mirror log arguments"; 9778c2ecf20Sopenharmony_ci return NULL; 9788c2ecf20Sopenharmony_ci } 9798c2ecf20Sopenharmony_ci 9808c2ecf20Sopenharmony_ci if (sscanf(argv[1], "%u%c", ¶m_count, &dummy) != 1) { 9818c2ecf20Sopenharmony_ci ti->error = "Invalid mirror log argument count"; 9828c2ecf20Sopenharmony_ci return NULL; 9838c2ecf20Sopenharmony_ci } 9848c2ecf20Sopenharmony_ci 9858c2ecf20Sopenharmony_ci *args_used = 2 + param_count; 9868c2ecf20Sopenharmony_ci 9878c2ecf20Sopenharmony_ci if (argc < *args_used) { 9888c2ecf20Sopenharmony_ci ti->error = "Insufficient mirror log arguments"; 9898c2ecf20Sopenharmony_ci return NULL; 9908c2ecf20Sopenharmony_ci } 9918c2ecf20Sopenharmony_ci 9928c2ecf20Sopenharmony_ci dl = dm_dirty_log_create(argv[0], ti, mirror_flush, param_count, 9938c2ecf20Sopenharmony_ci argv + 2); 9948c2ecf20Sopenharmony_ci if (!dl) { 9958c2ecf20Sopenharmony_ci ti->error = "Error creating mirror dirty log"; 9968c2ecf20Sopenharmony_ci return NULL; 9978c2ecf20Sopenharmony_ci } 9988c2ecf20Sopenharmony_ci 9998c2ecf20Sopenharmony_ci return dl; 10008c2ecf20Sopenharmony_ci} 10018c2ecf20Sopenharmony_ci 10028c2ecf20Sopenharmony_cistatic int parse_features(struct mirror_set *ms, unsigned argc, char **argv, 10038c2ecf20Sopenharmony_ci unsigned *args_used) 10048c2ecf20Sopenharmony_ci{ 10058c2ecf20Sopenharmony_ci unsigned num_features; 10068c2ecf20Sopenharmony_ci struct dm_target *ti = ms->ti; 10078c2ecf20Sopenharmony_ci char dummy; 10088c2ecf20Sopenharmony_ci int i; 10098c2ecf20Sopenharmony_ci 10108c2ecf20Sopenharmony_ci *args_used = 0; 10118c2ecf20Sopenharmony_ci 10128c2ecf20Sopenharmony_ci if (!argc) 10138c2ecf20Sopenharmony_ci return 0; 10148c2ecf20Sopenharmony_ci 10158c2ecf20Sopenharmony_ci if (sscanf(argv[0], "%u%c", &num_features, &dummy) != 1) { 10168c2ecf20Sopenharmony_ci ti->error = "Invalid number of features"; 10178c2ecf20Sopenharmony_ci return -EINVAL; 10188c2ecf20Sopenharmony_ci } 10198c2ecf20Sopenharmony_ci 10208c2ecf20Sopenharmony_ci argc--; 10218c2ecf20Sopenharmony_ci argv++; 10228c2ecf20Sopenharmony_ci (*args_used)++; 10238c2ecf20Sopenharmony_ci 10248c2ecf20Sopenharmony_ci if (num_features > argc) { 10258c2ecf20Sopenharmony_ci ti->error = "Not enough arguments to support feature count"; 10268c2ecf20Sopenharmony_ci return -EINVAL; 10278c2ecf20Sopenharmony_ci } 10288c2ecf20Sopenharmony_ci 10298c2ecf20Sopenharmony_ci for (i = 0; i < num_features; i++) { 10308c2ecf20Sopenharmony_ci if (!strcmp("handle_errors", argv[0])) 10318c2ecf20Sopenharmony_ci ms->features |= DM_RAID1_HANDLE_ERRORS; 10328c2ecf20Sopenharmony_ci else if (!strcmp("keep_log", argv[0])) 10338c2ecf20Sopenharmony_ci ms->features |= DM_RAID1_KEEP_LOG; 10348c2ecf20Sopenharmony_ci else { 10358c2ecf20Sopenharmony_ci ti->error = "Unrecognised feature requested"; 10368c2ecf20Sopenharmony_ci return -EINVAL; 10378c2ecf20Sopenharmony_ci } 10388c2ecf20Sopenharmony_ci 10398c2ecf20Sopenharmony_ci argc--; 10408c2ecf20Sopenharmony_ci argv++; 10418c2ecf20Sopenharmony_ci (*args_used)++; 10428c2ecf20Sopenharmony_ci } 10438c2ecf20Sopenharmony_ci if (!errors_handled(ms) && keep_log(ms)) { 10448c2ecf20Sopenharmony_ci ti->error = "keep_log feature requires the handle_errors feature"; 10458c2ecf20Sopenharmony_ci return -EINVAL; 10468c2ecf20Sopenharmony_ci } 10478c2ecf20Sopenharmony_ci 10488c2ecf20Sopenharmony_ci return 0; 10498c2ecf20Sopenharmony_ci} 10508c2ecf20Sopenharmony_ci 10518c2ecf20Sopenharmony_ci/* 10528c2ecf20Sopenharmony_ci * Construct a mirror mapping: 10538c2ecf20Sopenharmony_ci * 10548c2ecf20Sopenharmony_ci * log_type #log_params <log_params> 10558c2ecf20Sopenharmony_ci * #mirrors [mirror_path offset]{2,} 10568c2ecf20Sopenharmony_ci * [#features <features>] 10578c2ecf20Sopenharmony_ci * 10588c2ecf20Sopenharmony_ci * log_type is "core" or "disk" 10598c2ecf20Sopenharmony_ci * #log_params is between 1 and 3 10608c2ecf20Sopenharmony_ci * 10618c2ecf20Sopenharmony_ci * If present, supported features are "handle_errors" and "keep_log". 10628c2ecf20Sopenharmony_ci */ 10638c2ecf20Sopenharmony_cistatic int mirror_ctr(struct dm_target *ti, unsigned int argc, char **argv) 10648c2ecf20Sopenharmony_ci{ 10658c2ecf20Sopenharmony_ci int r; 10668c2ecf20Sopenharmony_ci unsigned int nr_mirrors, m, args_used; 10678c2ecf20Sopenharmony_ci struct mirror_set *ms; 10688c2ecf20Sopenharmony_ci struct dm_dirty_log *dl; 10698c2ecf20Sopenharmony_ci char dummy; 10708c2ecf20Sopenharmony_ci 10718c2ecf20Sopenharmony_ci dl = create_dirty_log(ti, argc, argv, &args_used); 10728c2ecf20Sopenharmony_ci if (!dl) 10738c2ecf20Sopenharmony_ci return -EINVAL; 10748c2ecf20Sopenharmony_ci 10758c2ecf20Sopenharmony_ci argv += args_used; 10768c2ecf20Sopenharmony_ci argc -= args_used; 10778c2ecf20Sopenharmony_ci 10788c2ecf20Sopenharmony_ci if (!argc || sscanf(argv[0], "%u%c", &nr_mirrors, &dummy) != 1 || 10798c2ecf20Sopenharmony_ci nr_mirrors < 2 || nr_mirrors > MAX_NR_MIRRORS) { 10808c2ecf20Sopenharmony_ci ti->error = "Invalid number of mirrors"; 10818c2ecf20Sopenharmony_ci dm_dirty_log_destroy(dl); 10828c2ecf20Sopenharmony_ci return -EINVAL; 10838c2ecf20Sopenharmony_ci } 10848c2ecf20Sopenharmony_ci 10858c2ecf20Sopenharmony_ci argv++, argc--; 10868c2ecf20Sopenharmony_ci 10878c2ecf20Sopenharmony_ci if (argc < nr_mirrors * 2) { 10888c2ecf20Sopenharmony_ci ti->error = "Too few mirror arguments"; 10898c2ecf20Sopenharmony_ci dm_dirty_log_destroy(dl); 10908c2ecf20Sopenharmony_ci return -EINVAL; 10918c2ecf20Sopenharmony_ci } 10928c2ecf20Sopenharmony_ci 10938c2ecf20Sopenharmony_ci ms = alloc_context(nr_mirrors, dl->type->get_region_size(dl), ti, dl); 10948c2ecf20Sopenharmony_ci if (!ms) { 10958c2ecf20Sopenharmony_ci dm_dirty_log_destroy(dl); 10968c2ecf20Sopenharmony_ci return -ENOMEM; 10978c2ecf20Sopenharmony_ci } 10988c2ecf20Sopenharmony_ci 10998c2ecf20Sopenharmony_ci /* Get the mirror parameter sets */ 11008c2ecf20Sopenharmony_ci for (m = 0; m < nr_mirrors; m++) { 11018c2ecf20Sopenharmony_ci r = get_mirror(ms, ti, m, argv); 11028c2ecf20Sopenharmony_ci if (r) { 11038c2ecf20Sopenharmony_ci free_context(ms, ti, m); 11048c2ecf20Sopenharmony_ci return r; 11058c2ecf20Sopenharmony_ci } 11068c2ecf20Sopenharmony_ci argv += 2; 11078c2ecf20Sopenharmony_ci argc -= 2; 11088c2ecf20Sopenharmony_ci } 11098c2ecf20Sopenharmony_ci 11108c2ecf20Sopenharmony_ci ti->private = ms; 11118c2ecf20Sopenharmony_ci 11128c2ecf20Sopenharmony_ci r = dm_set_target_max_io_len(ti, dm_rh_get_region_size(ms->rh)); 11138c2ecf20Sopenharmony_ci if (r) 11148c2ecf20Sopenharmony_ci goto err_free_context; 11158c2ecf20Sopenharmony_ci 11168c2ecf20Sopenharmony_ci ti->num_flush_bios = 1; 11178c2ecf20Sopenharmony_ci ti->num_discard_bios = 1; 11188c2ecf20Sopenharmony_ci ti->per_io_data_size = sizeof(struct dm_raid1_bio_record); 11198c2ecf20Sopenharmony_ci 11208c2ecf20Sopenharmony_ci ms->kmirrord_wq = alloc_workqueue("kmirrord", WQ_MEM_RECLAIM, 0); 11218c2ecf20Sopenharmony_ci if (!ms->kmirrord_wq) { 11228c2ecf20Sopenharmony_ci DMERR("couldn't start kmirrord"); 11238c2ecf20Sopenharmony_ci r = -ENOMEM; 11248c2ecf20Sopenharmony_ci goto err_free_context; 11258c2ecf20Sopenharmony_ci } 11268c2ecf20Sopenharmony_ci INIT_WORK(&ms->kmirrord_work, do_mirror); 11278c2ecf20Sopenharmony_ci timer_setup(&ms->timer, delayed_wake_fn, 0); 11288c2ecf20Sopenharmony_ci ms->timer_pending = 0; 11298c2ecf20Sopenharmony_ci INIT_WORK(&ms->trigger_event, trigger_event); 11308c2ecf20Sopenharmony_ci 11318c2ecf20Sopenharmony_ci r = parse_features(ms, argc, argv, &args_used); 11328c2ecf20Sopenharmony_ci if (r) 11338c2ecf20Sopenharmony_ci goto err_destroy_wq; 11348c2ecf20Sopenharmony_ci 11358c2ecf20Sopenharmony_ci argv += args_used; 11368c2ecf20Sopenharmony_ci argc -= args_used; 11378c2ecf20Sopenharmony_ci 11388c2ecf20Sopenharmony_ci /* 11398c2ecf20Sopenharmony_ci * Any read-balancing addition depends on the 11408c2ecf20Sopenharmony_ci * DM_RAID1_HANDLE_ERRORS flag being present. 11418c2ecf20Sopenharmony_ci * This is because the decision to balance depends 11428c2ecf20Sopenharmony_ci * on the sync state of a region. If the above 11438c2ecf20Sopenharmony_ci * flag is not present, we ignore errors; and 11448c2ecf20Sopenharmony_ci * the sync state may be inaccurate. 11458c2ecf20Sopenharmony_ci */ 11468c2ecf20Sopenharmony_ci 11478c2ecf20Sopenharmony_ci if (argc) { 11488c2ecf20Sopenharmony_ci ti->error = "Too many mirror arguments"; 11498c2ecf20Sopenharmony_ci r = -EINVAL; 11508c2ecf20Sopenharmony_ci goto err_destroy_wq; 11518c2ecf20Sopenharmony_ci } 11528c2ecf20Sopenharmony_ci 11538c2ecf20Sopenharmony_ci ms->kcopyd_client = dm_kcopyd_client_create(&dm_kcopyd_throttle); 11548c2ecf20Sopenharmony_ci if (IS_ERR(ms->kcopyd_client)) { 11558c2ecf20Sopenharmony_ci r = PTR_ERR(ms->kcopyd_client); 11568c2ecf20Sopenharmony_ci goto err_destroy_wq; 11578c2ecf20Sopenharmony_ci } 11588c2ecf20Sopenharmony_ci 11598c2ecf20Sopenharmony_ci wakeup_mirrord(ms); 11608c2ecf20Sopenharmony_ci return 0; 11618c2ecf20Sopenharmony_ci 11628c2ecf20Sopenharmony_cierr_destroy_wq: 11638c2ecf20Sopenharmony_ci destroy_workqueue(ms->kmirrord_wq); 11648c2ecf20Sopenharmony_cierr_free_context: 11658c2ecf20Sopenharmony_ci free_context(ms, ti, ms->nr_mirrors); 11668c2ecf20Sopenharmony_ci return r; 11678c2ecf20Sopenharmony_ci} 11688c2ecf20Sopenharmony_ci 11698c2ecf20Sopenharmony_cistatic void mirror_dtr(struct dm_target *ti) 11708c2ecf20Sopenharmony_ci{ 11718c2ecf20Sopenharmony_ci struct mirror_set *ms = (struct mirror_set *) ti->private; 11728c2ecf20Sopenharmony_ci 11738c2ecf20Sopenharmony_ci del_timer_sync(&ms->timer); 11748c2ecf20Sopenharmony_ci flush_workqueue(ms->kmirrord_wq); 11758c2ecf20Sopenharmony_ci flush_work(&ms->trigger_event); 11768c2ecf20Sopenharmony_ci dm_kcopyd_client_destroy(ms->kcopyd_client); 11778c2ecf20Sopenharmony_ci destroy_workqueue(ms->kmirrord_wq); 11788c2ecf20Sopenharmony_ci free_context(ms, ti, ms->nr_mirrors); 11798c2ecf20Sopenharmony_ci} 11808c2ecf20Sopenharmony_ci 11818c2ecf20Sopenharmony_ci/* 11828c2ecf20Sopenharmony_ci * Mirror mapping function 11838c2ecf20Sopenharmony_ci */ 11848c2ecf20Sopenharmony_cistatic int mirror_map(struct dm_target *ti, struct bio *bio) 11858c2ecf20Sopenharmony_ci{ 11868c2ecf20Sopenharmony_ci int r, rw = bio_data_dir(bio); 11878c2ecf20Sopenharmony_ci struct mirror *m; 11888c2ecf20Sopenharmony_ci struct mirror_set *ms = ti->private; 11898c2ecf20Sopenharmony_ci struct dm_dirty_log *log = dm_rh_dirty_log(ms->rh); 11908c2ecf20Sopenharmony_ci struct dm_raid1_bio_record *bio_record = 11918c2ecf20Sopenharmony_ci dm_per_bio_data(bio, sizeof(struct dm_raid1_bio_record)); 11928c2ecf20Sopenharmony_ci 11938c2ecf20Sopenharmony_ci bio_record->details.bi_disk = NULL; 11948c2ecf20Sopenharmony_ci 11958c2ecf20Sopenharmony_ci if (rw == WRITE) { 11968c2ecf20Sopenharmony_ci /* Save region for mirror_end_io() handler */ 11978c2ecf20Sopenharmony_ci bio_record->write_region = dm_rh_bio_to_region(ms->rh, bio); 11988c2ecf20Sopenharmony_ci queue_bio(ms, bio, rw); 11998c2ecf20Sopenharmony_ci return DM_MAPIO_SUBMITTED; 12008c2ecf20Sopenharmony_ci } 12018c2ecf20Sopenharmony_ci 12028c2ecf20Sopenharmony_ci r = log->type->in_sync(log, dm_rh_bio_to_region(ms->rh, bio), 0); 12038c2ecf20Sopenharmony_ci if (r < 0 && r != -EWOULDBLOCK) 12048c2ecf20Sopenharmony_ci return DM_MAPIO_KILL; 12058c2ecf20Sopenharmony_ci 12068c2ecf20Sopenharmony_ci /* 12078c2ecf20Sopenharmony_ci * If region is not in-sync queue the bio. 12088c2ecf20Sopenharmony_ci */ 12098c2ecf20Sopenharmony_ci if (!r || (r == -EWOULDBLOCK)) { 12108c2ecf20Sopenharmony_ci if (bio->bi_opf & REQ_RAHEAD) 12118c2ecf20Sopenharmony_ci return DM_MAPIO_KILL; 12128c2ecf20Sopenharmony_ci 12138c2ecf20Sopenharmony_ci queue_bio(ms, bio, rw); 12148c2ecf20Sopenharmony_ci return DM_MAPIO_SUBMITTED; 12158c2ecf20Sopenharmony_ci } 12168c2ecf20Sopenharmony_ci 12178c2ecf20Sopenharmony_ci /* 12188c2ecf20Sopenharmony_ci * The region is in-sync and we can perform reads directly. 12198c2ecf20Sopenharmony_ci * Store enough information so we can retry if it fails. 12208c2ecf20Sopenharmony_ci */ 12218c2ecf20Sopenharmony_ci m = choose_mirror(ms, bio->bi_iter.bi_sector); 12228c2ecf20Sopenharmony_ci if (unlikely(!m)) 12238c2ecf20Sopenharmony_ci return DM_MAPIO_KILL; 12248c2ecf20Sopenharmony_ci 12258c2ecf20Sopenharmony_ci dm_bio_record(&bio_record->details, bio); 12268c2ecf20Sopenharmony_ci bio_record->m = m; 12278c2ecf20Sopenharmony_ci 12288c2ecf20Sopenharmony_ci map_bio(m, bio); 12298c2ecf20Sopenharmony_ci 12308c2ecf20Sopenharmony_ci return DM_MAPIO_REMAPPED; 12318c2ecf20Sopenharmony_ci} 12328c2ecf20Sopenharmony_ci 12338c2ecf20Sopenharmony_cistatic int mirror_end_io(struct dm_target *ti, struct bio *bio, 12348c2ecf20Sopenharmony_ci blk_status_t *error) 12358c2ecf20Sopenharmony_ci{ 12368c2ecf20Sopenharmony_ci int rw = bio_data_dir(bio); 12378c2ecf20Sopenharmony_ci struct mirror_set *ms = (struct mirror_set *) ti->private; 12388c2ecf20Sopenharmony_ci struct mirror *m = NULL; 12398c2ecf20Sopenharmony_ci struct dm_bio_details *bd = NULL; 12408c2ecf20Sopenharmony_ci struct dm_raid1_bio_record *bio_record = 12418c2ecf20Sopenharmony_ci dm_per_bio_data(bio, sizeof(struct dm_raid1_bio_record)); 12428c2ecf20Sopenharmony_ci 12438c2ecf20Sopenharmony_ci /* 12448c2ecf20Sopenharmony_ci * We need to dec pending if this was a write. 12458c2ecf20Sopenharmony_ci */ 12468c2ecf20Sopenharmony_ci if (rw == WRITE) { 12478c2ecf20Sopenharmony_ci if (!(bio->bi_opf & REQ_PREFLUSH) && 12488c2ecf20Sopenharmony_ci bio_op(bio) != REQ_OP_DISCARD) 12498c2ecf20Sopenharmony_ci dm_rh_dec(ms->rh, bio_record->write_region); 12508c2ecf20Sopenharmony_ci return DM_ENDIO_DONE; 12518c2ecf20Sopenharmony_ci } 12528c2ecf20Sopenharmony_ci 12538c2ecf20Sopenharmony_ci if (*error == BLK_STS_NOTSUPP) 12548c2ecf20Sopenharmony_ci goto out; 12558c2ecf20Sopenharmony_ci 12568c2ecf20Sopenharmony_ci if (bio->bi_opf & REQ_RAHEAD) 12578c2ecf20Sopenharmony_ci goto out; 12588c2ecf20Sopenharmony_ci 12598c2ecf20Sopenharmony_ci if (unlikely(*error)) { 12608c2ecf20Sopenharmony_ci if (!bio_record->details.bi_disk) { 12618c2ecf20Sopenharmony_ci /* 12628c2ecf20Sopenharmony_ci * There wasn't enough memory to record necessary 12638c2ecf20Sopenharmony_ci * information for a retry or there was no other 12648c2ecf20Sopenharmony_ci * mirror in-sync. 12658c2ecf20Sopenharmony_ci */ 12668c2ecf20Sopenharmony_ci DMERR_LIMIT("Mirror read failed."); 12678c2ecf20Sopenharmony_ci return DM_ENDIO_DONE; 12688c2ecf20Sopenharmony_ci } 12698c2ecf20Sopenharmony_ci 12708c2ecf20Sopenharmony_ci m = bio_record->m; 12718c2ecf20Sopenharmony_ci 12728c2ecf20Sopenharmony_ci DMERR("Mirror read failed from %s. Trying alternative device.", 12738c2ecf20Sopenharmony_ci m->dev->name); 12748c2ecf20Sopenharmony_ci 12758c2ecf20Sopenharmony_ci fail_mirror(m, DM_RAID1_READ_ERROR); 12768c2ecf20Sopenharmony_ci 12778c2ecf20Sopenharmony_ci /* 12788c2ecf20Sopenharmony_ci * A failed read is requeued for another attempt using an intact 12798c2ecf20Sopenharmony_ci * mirror. 12808c2ecf20Sopenharmony_ci */ 12818c2ecf20Sopenharmony_ci if (default_ok(m) || mirror_available(ms, bio)) { 12828c2ecf20Sopenharmony_ci bd = &bio_record->details; 12838c2ecf20Sopenharmony_ci 12848c2ecf20Sopenharmony_ci dm_bio_restore(bd, bio); 12858c2ecf20Sopenharmony_ci bio_record->details.bi_disk = NULL; 12868c2ecf20Sopenharmony_ci bio->bi_status = 0; 12878c2ecf20Sopenharmony_ci 12888c2ecf20Sopenharmony_ci queue_bio(ms, bio, rw); 12898c2ecf20Sopenharmony_ci return DM_ENDIO_INCOMPLETE; 12908c2ecf20Sopenharmony_ci } 12918c2ecf20Sopenharmony_ci DMERR("All replicated volumes dead, failing I/O"); 12928c2ecf20Sopenharmony_ci } 12938c2ecf20Sopenharmony_ci 12948c2ecf20Sopenharmony_ciout: 12958c2ecf20Sopenharmony_ci bio_record->details.bi_disk = NULL; 12968c2ecf20Sopenharmony_ci 12978c2ecf20Sopenharmony_ci return DM_ENDIO_DONE; 12988c2ecf20Sopenharmony_ci} 12998c2ecf20Sopenharmony_ci 13008c2ecf20Sopenharmony_cistatic void mirror_presuspend(struct dm_target *ti) 13018c2ecf20Sopenharmony_ci{ 13028c2ecf20Sopenharmony_ci struct mirror_set *ms = (struct mirror_set *) ti->private; 13038c2ecf20Sopenharmony_ci struct dm_dirty_log *log = dm_rh_dirty_log(ms->rh); 13048c2ecf20Sopenharmony_ci 13058c2ecf20Sopenharmony_ci struct bio_list holds; 13068c2ecf20Sopenharmony_ci struct bio *bio; 13078c2ecf20Sopenharmony_ci 13088c2ecf20Sopenharmony_ci atomic_set(&ms->suspend, 1); 13098c2ecf20Sopenharmony_ci 13108c2ecf20Sopenharmony_ci /* 13118c2ecf20Sopenharmony_ci * Process bios in the hold list to start recovery waiting 13128c2ecf20Sopenharmony_ci * for bios in the hold list. After the process, no bio has 13138c2ecf20Sopenharmony_ci * a chance to be added in the hold list because ms->suspend 13148c2ecf20Sopenharmony_ci * is set. 13158c2ecf20Sopenharmony_ci */ 13168c2ecf20Sopenharmony_ci spin_lock_irq(&ms->lock); 13178c2ecf20Sopenharmony_ci holds = ms->holds; 13188c2ecf20Sopenharmony_ci bio_list_init(&ms->holds); 13198c2ecf20Sopenharmony_ci spin_unlock_irq(&ms->lock); 13208c2ecf20Sopenharmony_ci 13218c2ecf20Sopenharmony_ci while ((bio = bio_list_pop(&holds))) 13228c2ecf20Sopenharmony_ci hold_bio(ms, bio); 13238c2ecf20Sopenharmony_ci 13248c2ecf20Sopenharmony_ci /* 13258c2ecf20Sopenharmony_ci * We must finish up all the work that we've 13268c2ecf20Sopenharmony_ci * generated (i.e. recovery work). 13278c2ecf20Sopenharmony_ci */ 13288c2ecf20Sopenharmony_ci dm_rh_stop_recovery(ms->rh); 13298c2ecf20Sopenharmony_ci 13308c2ecf20Sopenharmony_ci wait_event(_kmirrord_recovery_stopped, 13318c2ecf20Sopenharmony_ci !dm_rh_recovery_in_flight(ms->rh)); 13328c2ecf20Sopenharmony_ci 13338c2ecf20Sopenharmony_ci if (log->type->presuspend && log->type->presuspend(log)) 13348c2ecf20Sopenharmony_ci /* FIXME: need better error handling */ 13358c2ecf20Sopenharmony_ci DMWARN("log presuspend failed"); 13368c2ecf20Sopenharmony_ci 13378c2ecf20Sopenharmony_ci /* 13388c2ecf20Sopenharmony_ci * Now that recovery is complete/stopped and the 13398c2ecf20Sopenharmony_ci * delayed bios are queued, we need to wait for 13408c2ecf20Sopenharmony_ci * the worker thread to complete. This way, 13418c2ecf20Sopenharmony_ci * we know that all of our I/O has been pushed. 13428c2ecf20Sopenharmony_ci */ 13438c2ecf20Sopenharmony_ci flush_workqueue(ms->kmirrord_wq); 13448c2ecf20Sopenharmony_ci} 13458c2ecf20Sopenharmony_ci 13468c2ecf20Sopenharmony_cistatic void mirror_postsuspend(struct dm_target *ti) 13478c2ecf20Sopenharmony_ci{ 13488c2ecf20Sopenharmony_ci struct mirror_set *ms = ti->private; 13498c2ecf20Sopenharmony_ci struct dm_dirty_log *log = dm_rh_dirty_log(ms->rh); 13508c2ecf20Sopenharmony_ci 13518c2ecf20Sopenharmony_ci if (log->type->postsuspend && log->type->postsuspend(log)) 13528c2ecf20Sopenharmony_ci /* FIXME: need better error handling */ 13538c2ecf20Sopenharmony_ci DMWARN("log postsuspend failed"); 13548c2ecf20Sopenharmony_ci} 13558c2ecf20Sopenharmony_ci 13568c2ecf20Sopenharmony_cistatic void mirror_resume(struct dm_target *ti) 13578c2ecf20Sopenharmony_ci{ 13588c2ecf20Sopenharmony_ci struct mirror_set *ms = ti->private; 13598c2ecf20Sopenharmony_ci struct dm_dirty_log *log = dm_rh_dirty_log(ms->rh); 13608c2ecf20Sopenharmony_ci 13618c2ecf20Sopenharmony_ci atomic_set(&ms->suspend, 0); 13628c2ecf20Sopenharmony_ci if (log->type->resume && log->type->resume(log)) 13638c2ecf20Sopenharmony_ci /* FIXME: need better error handling */ 13648c2ecf20Sopenharmony_ci DMWARN("log resume failed"); 13658c2ecf20Sopenharmony_ci dm_rh_start_recovery(ms->rh); 13668c2ecf20Sopenharmony_ci} 13678c2ecf20Sopenharmony_ci 13688c2ecf20Sopenharmony_ci/* 13698c2ecf20Sopenharmony_ci * device_status_char 13708c2ecf20Sopenharmony_ci * @m: mirror device/leg we want the status of 13718c2ecf20Sopenharmony_ci * 13728c2ecf20Sopenharmony_ci * We return one character representing the most severe error 13738c2ecf20Sopenharmony_ci * we have encountered. 13748c2ecf20Sopenharmony_ci * A => Alive - No failures 13758c2ecf20Sopenharmony_ci * D => Dead - A write failure occurred leaving mirror out-of-sync 13768c2ecf20Sopenharmony_ci * S => Sync - A sychronization failure occurred, mirror out-of-sync 13778c2ecf20Sopenharmony_ci * R => Read - A read failure occurred, mirror data unaffected 13788c2ecf20Sopenharmony_ci * 13798c2ecf20Sopenharmony_ci * Returns: <char> 13808c2ecf20Sopenharmony_ci */ 13818c2ecf20Sopenharmony_cistatic char device_status_char(struct mirror *m) 13828c2ecf20Sopenharmony_ci{ 13838c2ecf20Sopenharmony_ci if (!atomic_read(&(m->error_count))) 13848c2ecf20Sopenharmony_ci return 'A'; 13858c2ecf20Sopenharmony_ci 13868c2ecf20Sopenharmony_ci return (test_bit(DM_RAID1_FLUSH_ERROR, &(m->error_type))) ? 'F' : 13878c2ecf20Sopenharmony_ci (test_bit(DM_RAID1_WRITE_ERROR, &(m->error_type))) ? 'D' : 13888c2ecf20Sopenharmony_ci (test_bit(DM_RAID1_SYNC_ERROR, &(m->error_type))) ? 'S' : 13898c2ecf20Sopenharmony_ci (test_bit(DM_RAID1_READ_ERROR, &(m->error_type))) ? 'R' : 'U'; 13908c2ecf20Sopenharmony_ci} 13918c2ecf20Sopenharmony_ci 13928c2ecf20Sopenharmony_ci 13938c2ecf20Sopenharmony_cistatic void mirror_status(struct dm_target *ti, status_type_t type, 13948c2ecf20Sopenharmony_ci unsigned status_flags, char *result, unsigned maxlen) 13958c2ecf20Sopenharmony_ci{ 13968c2ecf20Sopenharmony_ci unsigned int m, sz = 0; 13978c2ecf20Sopenharmony_ci int num_feature_args = 0; 13988c2ecf20Sopenharmony_ci struct mirror_set *ms = (struct mirror_set *) ti->private; 13998c2ecf20Sopenharmony_ci struct dm_dirty_log *log = dm_rh_dirty_log(ms->rh); 14008c2ecf20Sopenharmony_ci char buffer[MAX_NR_MIRRORS + 1]; 14018c2ecf20Sopenharmony_ci 14028c2ecf20Sopenharmony_ci switch (type) { 14038c2ecf20Sopenharmony_ci case STATUSTYPE_INFO: 14048c2ecf20Sopenharmony_ci DMEMIT("%d ", ms->nr_mirrors); 14058c2ecf20Sopenharmony_ci for (m = 0; m < ms->nr_mirrors; m++) { 14068c2ecf20Sopenharmony_ci DMEMIT("%s ", ms->mirror[m].dev->name); 14078c2ecf20Sopenharmony_ci buffer[m] = device_status_char(&(ms->mirror[m])); 14088c2ecf20Sopenharmony_ci } 14098c2ecf20Sopenharmony_ci buffer[m] = '\0'; 14108c2ecf20Sopenharmony_ci 14118c2ecf20Sopenharmony_ci DMEMIT("%llu/%llu 1 %s ", 14128c2ecf20Sopenharmony_ci (unsigned long long)log->type->get_sync_count(log), 14138c2ecf20Sopenharmony_ci (unsigned long long)ms->nr_regions, buffer); 14148c2ecf20Sopenharmony_ci 14158c2ecf20Sopenharmony_ci sz += log->type->status(log, type, result+sz, maxlen-sz); 14168c2ecf20Sopenharmony_ci 14178c2ecf20Sopenharmony_ci break; 14188c2ecf20Sopenharmony_ci 14198c2ecf20Sopenharmony_ci case STATUSTYPE_TABLE: 14208c2ecf20Sopenharmony_ci sz = log->type->status(log, type, result, maxlen); 14218c2ecf20Sopenharmony_ci 14228c2ecf20Sopenharmony_ci DMEMIT("%d", ms->nr_mirrors); 14238c2ecf20Sopenharmony_ci for (m = 0; m < ms->nr_mirrors; m++) 14248c2ecf20Sopenharmony_ci DMEMIT(" %s %llu", ms->mirror[m].dev->name, 14258c2ecf20Sopenharmony_ci (unsigned long long)ms->mirror[m].offset); 14268c2ecf20Sopenharmony_ci 14278c2ecf20Sopenharmony_ci num_feature_args += !!errors_handled(ms); 14288c2ecf20Sopenharmony_ci num_feature_args += !!keep_log(ms); 14298c2ecf20Sopenharmony_ci if (num_feature_args) { 14308c2ecf20Sopenharmony_ci DMEMIT(" %d", num_feature_args); 14318c2ecf20Sopenharmony_ci if (errors_handled(ms)) 14328c2ecf20Sopenharmony_ci DMEMIT(" handle_errors"); 14338c2ecf20Sopenharmony_ci if (keep_log(ms)) 14348c2ecf20Sopenharmony_ci DMEMIT(" keep_log"); 14358c2ecf20Sopenharmony_ci } 14368c2ecf20Sopenharmony_ci 14378c2ecf20Sopenharmony_ci break; 14388c2ecf20Sopenharmony_ci } 14398c2ecf20Sopenharmony_ci} 14408c2ecf20Sopenharmony_ci 14418c2ecf20Sopenharmony_cistatic int mirror_iterate_devices(struct dm_target *ti, 14428c2ecf20Sopenharmony_ci iterate_devices_callout_fn fn, void *data) 14438c2ecf20Sopenharmony_ci{ 14448c2ecf20Sopenharmony_ci struct mirror_set *ms = ti->private; 14458c2ecf20Sopenharmony_ci int ret = 0; 14468c2ecf20Sopenharmony_ci unsigned i; 14478c2ecf20Sopenharmony_ci 14488c2ecf20Sopenharmony_ci for (i = 0; !ret && i < ms->nr_mirrors; i++) 14498c2ecf20Sopenharmony_ci ret = fn(ti, ms->mirror[i].dev, 14508c2ecf20Sopenharmony_ci ms->mirror[i].offset, ti->len, data); 14518c2ecf20Sopenharmony_ci 14528c2ecf20Sopenharmony_ci return ret; 14538c2ecf20Sopenharmony_ci} 14548c2ecf20Sopenharmony_ci 14558c2ecf20Sopenharmony_cistatic struct target_type mirror_target = { 14568c2ecf20Sopenharmony_ci .name = "mirror", 14578c2ecf20Sopenharmony_ci .version = {1, 14, 0}, 14588c2ecf20Sopenharmony_ci .module = THIS_MODULE, 14598c2ecf20Sopenharmony_ci .ctr = mirror_ctr, 14608c2ecf20Sopenharmony_ci .dtr = mirror_dtr, 14618c2ecf20Sopenharmony_ci .map = mirror_map, 14628c2ecf20Sopenharmony_ci .end_io = mirror_end_io, 14638c2ecf20Sopenharmony_ci .presuspend = mirror_presuspend, 14648c2ecf20Sopenharmony_ci .postsuspend = mirror_postsuspend, 14658c2ecf20Sopenharmony_ci .resume = mirror_resume, 14668c2ecf20Sopenharmony_ci .status = mirror_status, 14678c2ecf20Sopenharmony_ci .iterate_devices = mirror_iterate_devices, 14688c2ecf20Sopenharmony_ci}; 14698c2ecf20Sopenharmony_ci 14708c2ecf20Sopenharmony_cistatic int __init dm_mirror_init(void) 14718c2ecf20Sopenharmony_ci{ 14728c2ecf20Sopenharmony_ci int r; 14738c2ecf20Sopenharmony_ci 14748c2ecf20Sopenharmony_ci r = dm_register_target(&mirror_target); 14758c2ecf20Sopenharmony_ci if (r < 0) { 14768c2ecf20Sopenharmony_ci DMERR("Failed to register mirror target"); 14778c2ecf20Sopenharmony_ci goto bad_target; 14788c2ecf20Sopenharmony_ci } 14798c2ecf20Sopenharmony_ci 14808c2ecf20Sopenharmony_ci return 0; 14818c2ecf20Sopenharmony_ci 14828c2ecf20Sopenharmony_cibad_target: 14838c2ecf20Sopenharmony_ci return r; 14848c2ecf20Sopenharmony_ci} 14858c2ecf20Sopenharmony_ci 14868c2ecf20Sopenharmony_cistatic void __exit dm_mirror_exit(void) 14878c2ecf20Sopenharmony_ci{ 14888c2ecf20Sopenharmony_ci dm_unregister_target(&mirror_target); 14898c2ecf20Sopenharmony_ci} 14908c2ecf20Sopenharmony_ci 14918c2ecf20Sopenharmony_ci/* Module hooks */ 14928c2ecf20Sopenharmony_cimodule_init(dm_mirror_init); 14938c2ecf20Sopenharmony_cimodule_exit(dm_mirror_exit); 14948c2ecf20Sopenharmony_ci 14958c2ecf20Sopenharmony_ciMODULE_DESCRIPTION(DM_NAME " mirror target"); 14968c2ecf20Sopenharmony_ciMODULE_AUTHOR("Joe Thornber"); 14978c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL"); 1498