18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Copyright (C) 2015, SUSE 48c2ecf20Sopenharmony_ci */ 58c2ecf20Sopenharmony_ci 68c2ecf20Sopenharmony_ci 78c2ecf20Sopenharmony_ci#include <linux/module.h> 88c2ecf20Sopenharmony_ci#include <linux/kthread.h> 98c2ecf20Sopenharmony_ci#include <linux/dlm.h> 108c2ecf20Sopenharmony_ci#include <linux/sched.h> 118c2ecf20Sopenharmony_ci#include <linux/raid/md_p.h> 128c2ecf20Sopenharmony_ci#include "md.h" 138c2ecf20Sopenharmony_ci#include "md-bitmap.h" 148c2ecf20Sopenharmony_ci#include "md-cluster.h" 158c2ecf20Sopenharmony_ci 168c2ecf20Sopenharmony_ci#define LVB_SIZE 64 178c2ecf20Sopenharmony_ci#define NEW_DEV_TIMEOUT 5000 188c2ecf20Sopenharmony_ci 198c2ecf20Sopenharmony_cistruct dlm_lock_resource { 208c2ecf20Sopenharmony_ci dlm_lockspace_t *ls; 218c2ecf20Sopenharmony_ci struct dlm_lksb lksb; 228c2ecf20Sopenharmony_ci char *name; /* lock name. */ 238c2ecf20Sopenharmony_ci uint32_t flags; /* flags to pass to dlm_lock() */ 248c2ecf20Sopenharmony_ci wait_queue_head_t sync_locking; /* wait queue for synchronized locking */ 258c2ecf20Sopenharmony_ci bool sync_locking_done; 268c2ecf20Sopenharmony_ci void (*bast)(void *arg, int mode); /* blocking AST function pointer*/ 278c2ecf20Sopenharmony_ci struct mddev *mddev; /* pointing back to mddev. */ 288c2ecf20Sopenharmony_ci int mode; 298c2ecf20Sopenharmony_ci}; 308c2ecf20Sopenharmony_ci 318c2ecf20Sopenharmony_cistruct resync_info { 328c2ecf20Sopenharmony_ci __le64 lo; 338c2ecf20Sopenharmony_ci __le64 hi; 348c2ecf20Sopenharmony_ci}; 358c2ecf20Sopenharmony_ci 368c2ecf20Sopenharmony_ci/* md_cluster_info flags */ 378c2ecf20Sopenharmony_ci#define MD_CLUSTER_WAITING_FOR_NEWDISK 1 388c2ecf20Sopenharmony_ci#define MD_CLUSTER_SUSPEND_READ_BALANCING 2 398c2ecf20Sopenharmony_ci#define MD_CLUSTER_BEGIN_JOIN_CLUSTER 3 408c2ecf20Sopenharmony_ci 418c2ecf20Sopenharmony_ci/* Lock the send communication. This is done through 428c2ecf20Sopenharmony_ci * bit manipulation as opposed to a mutex in order to 438c2ecf20Sopenharmony_ci * accomodate lock and hold. See next comment. 448c2ecf20Sopenharmony_ci */ 458c2ecf20Sopenharmony_ci#define MD_CLUSTER_SEND_LOCK 4 468c2ecf20Sopenharmony_ci/* If cluster operations (such as adding a disk) must lock the 478c2ecf20Sopenharmony_ci * communication channel, so as to perform extra operations 488c2ecf20Sopenharmony_ci * (update metadata) and no other operation is allowed on the 498c2ecf20Sopenharmony_ci * MD. Token needs to be locked and held until the operation 508c2ecf20Sopenharmony_ci * completes witha md_update_sb(), which would eventually release 518c2ecf20Sopenharmony_ci * the lock. 528c2ecf20Sopenharmony_ci */ 538c2ecf20Sopenharmony_ci#define MD_CLUSTER_SEND_LOCKED_ALREADY 5 548c2ecf20Sopenharmony_ci/* We should receive message after node joined cluster and 558c2ecf20Sopenharmony_ci * set up all the related infos such as bitmap and personality */ 568c2ecf20Sopenharmony_ci#define MD_CLUSTER_ALREADY_IN_CLUSTER 6 578c2ecf20Sopenharmony_ci#define MD_CLUSTER_PENDING_RECV_EVENT 7 588c2ecf20Sopenharmony_ci#define MD_CLUSTER_HOLDING_MUTEX_FOR_RECVD 8 598c2ecf20Sopenharmony_ci 608c2ecf20Sopenharmony_cistruct md_cluster_info { 618c2ecf20Sopenharmony_ci struct mddev *mddev; /* the md device which md_cluster_info belongs to */ 628c2ecf20Sopenharmony_ci /* dlm lock space and resources for clustered raid. */ 638c2ecf20Sopenharmony_ci dlm_lockspace_t *lockspace; 648c2ecf20Sopenharmony_ci int slot_number; 658c2ecf20Sopenharmony_ci struct completion completion; 668c2ecf20Sopenharmony_ci struct mutex recv_mutex; 678c2ecf20Sopenharmony_ci struct dlm_lock_resource *bitmap_lockres; 688c2ecf20Sopenharmony_ci struct dlm_lock_resource **other_bitmap_lockres; 698c2ecf20Sopenharmony_ci struct dlm_lock_resource *resync_lockres; 708c2ecf20Sopenharmony_ci struct list_head suspend_list; 718c2ecf20Sopenharmony_ci 728c2ecf20Sopenharmony_ci spinlock_t suspend_lock; 738c2ecf20Sopenharmony_ci /* record the region which write should be suspended */ 748c2ecf20Sopenharmony_ci sector_t suspend_lo; 758c2ecf20Sopenharmony_ci sector_t suspend_hi; 768c2ecf20Sopenharmony_ci int suspend_from; /* the slot which broadcast suspend_lo/hi */ 778c2ecf20Sopenharmony_ci 788c2ecf20Sopenharmony_ci struct md_thread *recovery_thread; 798c2ecf20Sopenharmony_ci unsigned long recovery_map; 808c2ecf20Sopenharmony_ci /* communication loc resources */ 818c2ecf20Sopenharmony_ci struct dlm_lock_resource *ack_lockres; 828c2ecf20Sopenharmony_ci struct dlm_lock_resource *message_lockres; 838c2ecf20Sopenharmony_ci struct dlm_lock_resource *token_lockres; 848c2ecf20Sopenharmony_ci struct dlm_lock_resource *no_new_dev_lockres; 858c2ecf20Sopenharmony_ci struct md_thread *recv_thread; 868c2ecf20Sopenharmony_ci struct completion newdisk_completion; 878c2ecf20Sopenharmony_ci wait_queue_head_t wait; 888c2ecf20Sopenharmony_ci unsigned long state; 898c2ecf20Sopenharmony_ci /* record the region in RESYNCING message */ 908c2ecf20Sopenharmony_ci sector_t sync_low; 918c2ecf20Sopenharmony_ci sector_t sync_hi; 928c2ecf20Sopenharmony_ci}; 938c2ecf20Sopenharmony_ci 948c2ecf20Sopenharmony_cienum msg_type { 958c2ecf20Sopenharmony_ci METADATA_UPDATED = 0, 968c2ecf20Sopenharmony_ci RESYNCING, 978c2ecf20Sopenharmony_ci NEWDISK, 988c2ecf20Sopenharmony_ci REMOVE, 998c2ecf20Sopenharmony_ci RE_ADD, 1008c2ecf20Sopenharmony_ci BITMAP_NEEDS_SYNC, 1018c2ecf20Sopenharmony_ci CHANGE_CAPACITY, 1028c2ecf20Sopenharmony_ci BITMAP_RESIZE, 1038c2ecf20Sopenharmony_ci}; 1048c2ecf20Sopenharmony_ci 1058c2ecf20Sopenharmony_cistruct cluster_msg { 1068c2ecf20Sopenharmony_ci __le32 type; 1078c2ecf20Sopenharmony_ci __le32 slot; 1088c2ecf20Sopenharmony_ci /* TODO: Unionize this for smaller footprint */ 1098c2ecf20Sopenharmony_ci __le64 low; 1108c2ecf20Sopenharmony_ci __le64 high; 1118c2ecf20Sopenharmony_ci char uuid[16]; 1128c2ecf20Sopenharmony_ci __le32 raid_slot; 1138c2ecf20Sopenharmony_ci}; 1148c2ecf20Sopenharmony_ci 1158c2ecf20Sopenharmony_cistatic void sync_ast(void *arg) 1168c2ecf20Sopenharmony_ci{ 1178c2ecf20Sopenharmony_ci struct dlm_lock_resource *res; 1188c2ecf20Sopenharmony_ci 1198c2ecf20Sopenharmony_ci res = arg; 1208c2ecf20Sopenharmony_ci res->sync_locking_done = true; 1218c2ecf20Sopenharmony_ci wake_up(&res->sync_locking); 1228c2ecf20Sopenharmony_ci} 1238c2ecf20Sopenharmony_ci 1248c2ecf20Sopenharmony_cistatic int dlm_lock_sync(struct dlm_lock_resource *res, int mode) 1258c2ecf20Sopenharmony_ci{ 1268c2ecf20Sopenharmony_ci int ret = 0; 1278c2ecf20Sopenharmony_ci 1288c2ecf20Sopenharmony_ci ret = dlm_lock(res->ls, mode, &res->lksb, 1298c2ecf20Sopenharmony_ci res->flags, res->name, strlen(res->name), 1308c2ecf20Sopenharmony_ci 0, sync_ast, res, res->bast); 1318c2ecf20Sopenharmony_ci if (ret) 1328c2ecf20Sopenharmony_ci return ret; 1338c2ecf20Sopenharmony_ci wait_event(res->sync_locking, res->sync_locking_done); 1348c2ecf20Sopenharmony_ci res->sync_locking_done = false; 1358c2ecf20Sopenharmony_ci if (res->lksb.sb_status == 0) 1368c2ecf20Sopenharmony_ci res->mode = mode; 1378c2ecf20Sopenharmony_ci return res->lksb.sb_status; 1388c2ecf20Sopenharmony_ci} 1398c2ecf20Sopenharmony_ci 1408c2ecf20Sopenharmony_cistatic int dlm_unlock_sync(struct dlm_lock_resource *res) 1418c2ecf20Sopenharmony_ci{ 1428c2ecf20Sopenharmony_ci return dlm_lock_sync(res, DLM_LOCK_NL); 1438c2ecf20Sopenharmony_ci} 1448c2ecf20Sopenharmony_ci 1458c2ecf20Sopenharmony_ci/* 1468c2ecf20Sopenharmony_ci * An variation of dlm_lock_sync, which make lock request could 1478c2ecf20Sopenharmony_ci * be interrupted 1488c2ecf20Sopenharmony_ci */ 1498c2ecf20Sopenharmony_cistatic int dlm_lock_sync_interruptible(struct dlm_lock_resource *res, int mode, 1508c2ecf20Sopenharmony_ci struct mddev *mddev) 1518c2ecf20Sopenharmony_ci{ 1528c2ecf20Sopenharmony_ci int ret = 0; 1538c2ecf20Sopenharmony_ci 1548c2ecf20Sopenharmony_ci ret = dlm_lock(res->ls, mode, &res->lksb, 1558c2ecf20Sopenharmony_ci res->flags, res->name, strlen(res->name), 1568c2ecf20Sopenharmony_ci 0, sync_ast, res, res->bast); 1578c2ecf20Sopenharmony_ci if (ret) 1588c2ecf20Sopenharmony_ci return ret; 1598c2ecf20Sopenharmony_ci 1608c2ecf20Sopenharmony_ci wait_event(res->sync_locking, res->sync_locking_done 1618c2ecf20Sopenharmony_ci || kthread_should_stop() 1628c2ecf20Sopenharmony_ci || test_bit(MD_CLOSING, &mddev->flags)); 1638c2ecf20Sopenharmony_ci if (!res->sync_locking_done) { 1648c2ecf20Sopenharmony_ci /* 1658c2ecf20Sopenharmony_ci * the convert queue contains the lock request when request is 1668c2ecf20Sopenharmony_ci * interrupted, and sync_ast could still be run, so need to 1678c2ecf20Sopenharmony_ci * cancel the request and reset completion 1688c2ecf20Sopenharmony_ci */ 1698c2ecf20Sopenharmony_ci ret = dlm_unlock(res->ls, res->lksb.sb_lkid, DLM_LKF_CANCEL, 1708c2ecf20Sopenharmony_ci &res->lksb, res); 1718c2ecf20Sopenharmony_ci res->sync_locking_done = false; 1728c2ecf20Sopenharmony_ci if (unlikely(ret != 0)) 1738c2ecf20Sopenharmony_ci pr_info("failed to cancel previous lock request " 1748c2ecf20Sopenharmony_ci "%s return %d\n", res->name, ret); 1758c2ecf20Sopenharmony_ci return -EPERM; 1768c2ecf20Sopenharmony_ci } else 1778c2ecf20Sopenharmony_ci res->sync_locking_done = false; 1788c2ecf20Sopenharmony_ci if (res->lksb.sb_status == 0) 1798c2ecf20Sopenharmony_ci res->mode = mode; 1808c2ecf20Sopenharmony_ci return res->lksb.sb_status; 1818c2ecf20Sopenharmony_ci} 1828c2ecf20Sopenharmony_ci 1838c2ecf20Sopenharmony_cistatic struct dlm_lock_resource *lockres_init(struct mddev *mddev, 1848c2ecf20Sopenharmony_ci char *name, void (*bastfn)(void *arg, int mode), int with_lvb) 1858c2ecf20Sopenharmony_ci{ 1868c2ecf20Sopenharmony_ci struct dlm_lock_resource *res = NULL; 1878c2ecf20Sopenharmony_ci int ret, namelen; 1888c2ecf20Sopenharmony_ci struct md_cluster_info *cinfo = mddev->cluster_info; 1898c2ecf20Sopenharmony_ci 1908c2ecf20Sopenharmony_ci res = kzalloc(sizeof(struct dlm_lock_resource), GFP_KERNEL); 1918c2ecf20Sopenharmony_ci if (!res) 1928c2ecf20Sopenharmony_ci return NULL; 1938c2ecf20Sopenharmony_ci init_waitqueue_head(&res->sync_locking); 1948c2ecf20Sopenharmony_ci res->sync_locking_done = false; 1958c2ecf20Sopenharmony_ci res->ls = cinfo->lockspace; 1968c2ecf20Sopenharmony_ci res->mddev = mddev; 1978c2ecf20Sopenharmony_ci res->mode = DLM_LOCK_IV; 1988c2ecf20Sopenharmony_ci namelen = strlen(name); 1998c2ecf20Sopenharmony_ci res->name = kzalloc(namelen + 1, GFP_KERNEL); 2008c2ecf20Sopenharmony_ci if (!res->name) { 2018c2ecf20Sopenharmony_ci pr_err("md-cluster: Unable to allocate resource name for resource %s\n", name); 2028c2ecf20Sopenharmony_ci goto out_err; 2038c2ecf20Sopenharmony_ci } 2048c2ecf20Sopenharmony_ci strlcpy(res->name, name, namelen + 1); 2058c2ecf20Sopenharmony_ci if (with_lvb) { 2068c2ecf20Sopenharmony_ci res->lksb.sb_lvbptr = kzalloc(LVB_SIZE, GFP_KERNEL); 2078c2ecf20Sopenharmony_ci if (!res->lksb.sb_lvbptr) { 2088c2ecf20Sopenharmony_ci pr_err("md-cluster: Unable to allocate LVB for resource %s\n", name); 2098c2ecf20Sopenharmony_ci goto out_err; 2108c2ecf20Sopenharmony_ci } 2118c2ecf20Sopenharmony_ci res->flags = DLM_LKF_VALBLK; 2128c2ecf20Sopenharmony_ci } 2138c2ecf20Sopenharmony_ci 2148c2ecf20Sopenharmony_ci if (bastfn) 2158c2ecf20Sopenharmony_ci res->bast = bastfn; 2168c2ecf20Sopenharmony_ci 2178c2ecf20Sopenharmony_ci res->flags |= DLM_LKF_EXPEDITE; 2188c2ecf20Sopenharmony_ci 2198c2ecf20Sopenharmony_ci ret = dlm_lock_sync(res, DLM_LOCK_NL); 2208c2ecf20Sopenharmony_ci if (ret) { 2218c2ecf20Sopenharmony_ci pr_err("md-cluster: Unable to lock NL on new lock resource %s\n", name); 2228c2ecf20Sopenharmony_ci goto out_err; 2238c2ecf20Sopenharmony_ci } 2248c2ecf20Sopenharmony_ci res->flags &= ~DLM_LKF_EXPEDITE; 2258c2ecf20Sopenharmony_ci res->flags |= DLM_LKF_CONVERT; 2268c2ecf20Sopenharmony_ci 2278c2ecf20Sopenharmony_ci return res; 2288c2ecf20Sopenharmony_ciout_err: 2298c2ecf20Sopenharmony_ci kfree(res->lksb.sb_lvbptr); 2308c2ecf20Sopenharmony_ci kfree(res->name); 2318c2ecf20Sopenharmony_ci kfree(res); 2328c2ecf20Sopenharmony_ci return NULL; 2338c2ecf20Sopenharmony_ci} 2348c2ecf20Sopenharmony_ci 2358c2ecf20Sopenharmony_cistatic void lockres_free(struct dlm_lock_resource *res) 2368c2ecf20Sopenharmony_ci{ 2378c2ecf20Sopenharmony_ci int ret = 0; 2388c2ecf20Sopenharmony_ci 2398c2ecf20Sopenharmony_ci if (!res) 2408c2ecf20Sopenharmony_ci return; 2418c2ecf20Sopenharmony_ci 2428c2ecf20Sopenharmony_ci /* 2438c2ecf20Sopenharmony_ci * use FORCEUNLOCK flag, so we can unlock even the lock is on the 2448c2ecf20Sopenharmony_ci * waiting or convert queue 2458c2ecf20Sopenharmony_ci */ 2468c2ecf20Sopenharmony_ci ret = dlm_unlock(res->ls, res->lksb.sb_lkid, DLM_LKF_FORCEUNLOCK, 2478c2ecf20Sopenharmony_ci &res->lksb, res); 2488c2ecf20Sopenharmony_ci if (unlikely(ret != 0)) 2498c2ecf20Sopenharmony_ci pr_err("failed to unlock %s return %d\n", res->name, ret); 2508c2ecf20Sopenharmony_ci else 2518c2ecf20Sopenharmony_ci wait_event(res->sync_locking, res->sync_locking_done); 2528c2ecf20Sopenharmony_ci 2538c2ecf20Sopenharmony_ci kfree(res->name); 2548c2ecf20Sopenharmony_ci kfree(res->lksb.sb_lvbptr); 2558c2ecf20Sopenharmony_ci kfree(res); 2568c2ecf20Sopenharmony_ci} 2578c2ecf20Sopenharmony_ci 2588c2ecf20Sopenharmony_cistatic void add_resync_info(struct dlm_lock_resource *lockres, 2598c2ecf20Sopenharmony_ci sector_t lo, sector_t hi) 2608c2ecf20Sopenharmony_ci{ 2618c2ecf20Sopenharmony_ci struct resync_info *ri; 2628c2ecf20Sopenharmony_ci 2638c2ecf20Sopenharmony_ci ri = (struct resync_info *)lockres->lksb.sb_lvbptr; 2648c2ecf20Sopenharmony_ci ri->lo = cpu_to_le64(lo); 2658c2ecf20Sopenharmony_ci ri->hi = cpu_to_le64(hi); 2668c2ecf20Sopenharmony_ci} 2678c2ecf20Sopenharmony_ci 2688c2ecf20Sopenharmony_cistatic int read_resync_info(struct mddev *mddev, 2698c2ecf20Sopenharmony_ci struct dlm_lock_resource *lockres) 2708c2ecf20Sopenharmony_ci{ 2718c2ecf20Sopenharmony_ci struct resync_info ri; 2728c2ecf20Sopenharmony_ci struct md_cluster_info *cinfo = mddev->cluster_info; 2738c2ecf20Sopenharmony_ci int ret = 0; 2748c2ecf20Sopenharmony_ci 2758c2ecf20Sopenharmony_ci dlm_lock_sync(lockres, DLM_LOCK_CR); 2768c2ecf20Sopenharmony_ci memcpy(&ri, lockres->lksb.sb_lvbptr, sizeof(struct resync_info)); 2778c2ecf20Sopenharmony_ci if (le64_to_cpu(ri.hi) > 0) { 2788c2ecf20Sopenharmony_ci cinfo->suspend_hi = le64_to_cpu(ri.hi); 2798c2ecf20Sopenharmony_ci cinfo->suspend_lo = le64_to_cpu(ri.lo); 2808c2ecf20Sopenharmony_ci ret = 1; 2818c2ecf20Sopenharmony_ci } 2828c2ecf20Sopenharmony_ci dlm_unlock_sync(lockres); 2838c2ecf20Sopenharmony_ci return ret; 2848c2ecf20Sopenharmony_ci} 2858c2ecf20Sopenharmony_ci 2868c2ecf20Sopenharmony_cistatic void recover_bitmaps(struct md_thread *thread) 2878c2ecf20Sopenharmony_ci{ 2888c2ecf20Sopenharmony_ci struct mddev *mddev = thread->mddev; 2898c2ecf20Sopenharmony_ci struct md_cluster_info *cinfo = mddev->cluster_info; 2908c2ecf20Sopenharmony_ci struct dlm_lock_resource *bm_lockres; 2918c2ecf20Sopenharmony_ci char str[64]; 2928c2ecf20Sopenharmony_ci int slot, ret; 2938c2ecf20Sopenharmony_ci sector_t lo, hi; 2948c2ecf20Sopenharmony_ci 2958c2ecf20Sopenharmony_ci while (cinfo->recovery_map) { 2968c2ecf20Sopenharmony_ci slot = fls64((u64)cinfo->recovery_map) - 1; 2978c2ecf20Sopenharmony_ci 2988c2ecf20Sopenharmony_ci snprintf(str, 64, "bitmap%04d", slot); 2998c2ecf20Sopenharmony_ci bm_lockres = lockres_init(mddev, str, NULL, 1); 3008c2ecf20Sopenharmony_ci if (!bm_lockres) { 3018c2ecf20Sopenharmony_ci pr_err("md-cluster: Cannot initialize bitmaps\n"); 3028c2ecf20Sopenharmony_ci goto clear_bit; 3038c2ecf20Sopenharmony_ci } 3048c2ecf20Sopenharmony_ci 3058c2ecf20Sopenharmony_ci ret = dlm_lock_sync_interruptible(bm_lockres, DLM_LOCK_PW, mddev); 3068c2ecf20Sopenharmony_ci if (ret) { 3078c2ecf20Sopenharmony_ci pr_err("md-cluster: Could not DLM lock %s: %d\n", 3088c2ecf20Sopenharmony_ci str, ret); 3098c2ecf20Sopenharmony_ci goto clear_bit; 3108c2ecf20Sopenharmony_ci } 3118c2ecf20Sopenharmony_ci ret = md_bitmap_copy_from_slot(mddev, slot, &lo, &hi, true); 3128c2ecf20Sopenharmony_ci if (ret) { 3138c2ecf20Sopenharmony_ci pr_err("md-cluster: Could not copy data from bitmap %d\n", slot); 3148c2ecf20Sopenharmony_ci goto clear_bit; 3158c2ecf20Sopenharmony_ci } 3168c2ecf20Sopenharmony_ci 3178c2ecf20Sopenharmony_ci /* Clear suspend_area associated with the bitmap */ 3188c2ecf20Sopenharmony_ci spin_lock_irq(&cinfo->suspend_lock); 3198c2ecf20Sopenharmony_ci cinfo->suspend_hi = 0; 3208c2ecf20Sopenharmony_ci cinfo->suspend_lo = 0; 3218c2ecf20Sopenharmony_ci cinfo->suspend_from = -1; 3228c2ecf20Sopenharmony_ci spin_unlock_irq(&cinfo->suspend_lock); 3238c2ecf20Sopenharmony_ci 3248c2ecf20Sopenharmony_ci /* Kick off a reshape if needed */ 3258c2ecf20Sopenharmony_ci if (test_bit(MD_RESYNCING_REMOTE, &mddev->recovery) && 3268c2ecf20Sopenharmony_ci test_bit(MD_RECOVERY_RESHAPE, &mddev->recovery) && 3278c2ecf20Sopenharmony_ci mddev->reshape_position != MaxSector) 3288c2ecf20Sopenharmony_ci md_wakeup_thread(mddev->sync_thread); 3298c2ecf20Sopenharmony_ci 3308c2ecf20Sopenharmony_ci if (hi > 0) { 3318c2ecf20Sopenharmony_ci if (lo < mddev->recovery_cp) 3328c2ecf20Sopenharmony_ci mddev->recovery_cp = lo; 3338c2ecf20Sopenharmony_ci /* wake up thread to continue resync in case resync 3348c2ecf20Sopenharmony_ci * is not finished */ 3358c2ecf20Sopenharmony_ci if (mddev->recovery_cp != MaxSector) { 3368c2ecf20Sopenharmony_ci /* 3378c2ecf20Sopenharmony_ci * clear the REMOTE flag since we will launch 3388c2ecf20Sopenharmony_ci * resync thread in current node. 3398c2ecf20Sopenharmony_ci */ 3408c2ecf20Sopenharmony_ci clear_bit(MD_RESYNCING_REMOTE, 3418c2ecf20Sopenharmony_ci &mddev->recovery); 3428c2ecf20Sopenharmony_ci set_bit(MD_RECOVERY_NEEDED, &mddev->recovery); 3438c2ecf20Sopenharmony_ci md_wakeup_thread(mddev->thread); 3448c2ecf20Sopenharmony_ci } 3458c2ecf20Sopenharmony_ci } 3468c2ecf20Sopenharmony_ciclear_bit: 3478c2ecf20Sopenharmony_ci lockres_free(bm_lockres); 3488c2ecf20Sopenharmony_ci clear_bit(slot, &cinfo->recovery_map); 3498c2ecf20Sopenharmony_ci } 3508c2ecf20Sopenharmony_ci} 3518c2ecf20Sopenharmony_ci 3528c2ecf20Sopenharmony_cistatic void recover_prep(void *arg) 3538c2ecf20Sopenharmony_ci{ 3548c2ecf20Sopenharmony_ci struct mddev *mddev = arg; 3558c2ecf20Sopenharmony_ci struct md_cluster_info *cinfo = mddev->cluster_info; 3568c2ecf20Sopenharmony_ci set_bit(MD_CLUSTER_SUSPEND_READ_BALANCING, &cinfo->state); 3578c2ecf20Sopenharmony_ci} 3588c2ecf20Sopenharmony_ci 3598c2ecf20Sopenharmony_cistatic void __recover_slot(struct mddev *mddev, int slot) 3608c2ecf20Sopenharmony_ci{ 3618c2ecf20Sopenharmony_ci struct md_cluster_info *cinfo = mddev->cluster_info; 3628c2ecf20Sopenharmony_ci 3638c2ecf20Sopenharmony_ci set_bit(slot, &cinfo->recovery_map); 3648c2ecf20Sopenharmony_ci if (!cinfo->recovery_thread) { 3658c2ecf20Sopenharmony_ci cinfo->recovery_thread = md_register_thread(recover_bitmaps, 3668c2ecf20Sopenharmony_ci mddev, "recover"); 3678c2ecf20Sopenharmony_ci if (!cinfo->recovery_thread) { 3688c2ecf20Sopenharmony_ci pr_warn("md-cluster: Could not create recovery thread\n"); 3698c2ecf20Sopenharmony_ci return; 3708c2ecf20Sopenharmony_ci } 3718c2ecf20Sopenharmony_ci } 3728c2ecf20Sopenharmony_ci md_wakeup_thread(cinfo->recovery_thread); 3738c2ecf20Sopenharmony_ci} 3748c2ecf20Sopenharmony_ci 3758c2ecf20Sopenharmony_cistatic void recover_slot(void *arg, struct dlm_slot *slot) 3768c2ecf20Sopenharmony_ci{ 3778c2ecf20Sopenharmony_ci struct mddev *mddev = arg; 3788c2ecf20Sopenharmony_ci struct md_cluster_info *cinfo = mddev->cluster_info; 3798c2ecf20Sopenharmony_ci 3808c2ecf20Sopenharmony_ci pr_info("md-cluster: %s Node %d/%d down. My slot: %d. Initiating recovery.\n", 3818c2ecf20Sopenharmony_ci mddev->bitmap_info.cluster_name, 3828c2ecf20Sopenharmony_ci slot->nodeid, slot->slot, 3838c2ecf20Sopenharmony_ci cinfo->slot_number); 3848c2ecf20Sopenharmony_ci /* deduct one since dlm slot starts from one while the num of 3858c2ecf20Sopenharmony_ci * cluster-md begins with 0 */ 3868c2ecf20Sopenharmony_ci __recover_slot(mddev, slot->slot - 1); 3878c2ecf20Sopenharmony_ci} 3888c2ecf20Sopenharmony_ci 3898c2ecf20Sopenharmony_cistatic void recover_done(void *arg, struct dlm_slot *slots, 3908c2ecf20Sopenharmony_ci int num_slots, int our_slot, 3918c2ecf20Sopenharmony_ci uint32_t generation) 3928c2ecf20Sopenharmony_ci{ 3938c2ecf20Sopenharmony_ci struct mddev *mddev = arg; 3948c2ecf20Sopenharmony_ci struct md_cluster_info *cinfo = mddev->cluster_info; 3958c2ecf20Sopenharmony_ci 3968c2ecf20Sopenharmony_ci cinfo->slot_number = our_slot; 3978c2ecf20Sopenharmony_ci /* completion is only need to be complete when node join cluster, 3988c2ecf20Sopenharmony_ci * it doesn't need to run during another node's failure */ 3998c2ecf20Sopenharmony_ci if (test_bit(MD_CLUSTER_BEGIN_JOIN_CLUSTER, &cinfo->state)) { 4008c2ecf20Sopenharmony_ci complete(&cinfo->completion); 4018c2ecf20Sopenharmony_ci clear_bit(MD_CLUSTER_BEGIN_JOIN_CLUSTER, &cinfo->state); 4028c2ecf20Sopenharmony_ci } 4038c2ecf20Sopenharmony_ci clear_bit(MD_CLUSTER_SUSPEND_READ_BALANCING, &cinfo->state); 4048c2ecf20Sopenharmony_ci} 4058c2ecf20Sopenharmony_ci 4068c2ecf20Sopenharmony_ci/* the ops is called when node join the cluster, and do lock recovery 4078c2ecf20Sopenharmony_ci * if node failure occurs */ 4088c2ecf20Sopenharmony_cistatic const struct dlm_lockspace_ops md_ls_ops = { 4098c2ecf20Sopenharmony_ci .recover_prep = recover_prep, 4108c2ecf20Sopenharmony_ci .recover_slot = recover_slot, 4118c2ecf20Sopenharmony_ci .recover_done = recover_done, 4128c2ecf20Sopenharmony_ci}; 4138c2ecf20Sopenharmony_ci 4148c2ecf20Sopenharmony_ci/* 4158c2ecf20Sopenharmony_ci * The BAST function for the ack lock resource 4168c2ecf20Sopenharmony_ci * This function wakes up the receive thread in 4178c2ecf20Sopenharmony_ci * order to receive and process the message. 4188c2ecf20Sopenharmony_ci */ 4198c2ecf20Sopenharmony_cistatic void ack_bast(void *arg, int mode) 4208c2ecf20Sopenharmony_ci{ 4218c2ecf20Sopenharmony_ci struct dlm_lock_resource *res = arg; 4228c2ecf20Sopenharmony_ci struct md_cluster_info *cinfo = res->mddev->cluster_info; 4238c2ecf20Sopenharmony_ci 4248c2ecf20Sopenharmony_ci if (mode == DLM_LOCK_EX) { 4258c2ecf20Sopenharmony_ci if (test_bit(MD_CLUSTER_ALREADY_IN_CLUSTER, &cinfo->state)) 4268c2ecf20Sopenharmony_ci md_wakeup_thread(cinfo->recv_thread); 4278c2ecf20Sopenharmony_ci else 4288c2ecf20Sopenharmony_ci set_bit(MD_CLUSTER_PENDING_RECV_EVENT, &cinfo->state); 4298c2ecf20Sopenharmony_ci } 4308c2ecf20Sopenharmony_ci} 4318c2ecf20Sopenharmony_ci 4328c2ecf20Sopenharmony_cistatic void remove_suspend_info(struct mddev *mddev, int slot) 4338c2ecf20Sopenharmony_ci{ 4348c2ecf20Sopenharmony_ci struct md_cluster_info *cinfo = mddev->cluster_info; 4358c2ecf20Sopenharmony_ci mddev->pers->quiesce(mddev, 1); 4368c2ecf20Sopenharmony_ci spin_lock_irq(&cinfo->suspend_lock); 4378c2ecf20Sopenharmony_ci cinfo->suspend_hi = 0; 4388c2ecf20Sopenharmony_ci cinfo->suspend_lo = 0; 4398c2ecf20Sopenharmony_ci spin_unlock_irq(&cinfo->suspend_lock); 4408c2ecf20Sopenharmony_ci mddev->pers->quiesce(mddev, 0); 4418c2ecf20Sopenharmony_ci} 4428c2ecf20Sopenharmony_ci 4438c2ecf20Sopenharmony_cistatic void process_suspend_info(struct mddev *mddev, 4448c2ecf20Sopenharmony_ci int slot, sector_t lo, sector_t hi) 4458c2ecf20Sopenharmony_ci{ 4468c2ecf20Sopenharmony_ci struct md_cluster_info *cinfo = mddev->cluster_info; 4478c2ecf20Sopenharmony_ci struct mdp_superblock_1 *sb = NULL; 4488c2ecf20Sopenharmony_ci struct md_rdev *rdev; 4498c2ecf20Sopenharmony_ci 4508c2ecf20Sopenharmony_ci if (!hi) { 4518c2ecf20Sopenharmony_ci /* 4528c2ecf20Sopenharmony_ci * clear the REMOTE flag since resync or recovery is finished 4538c2ecf20Sopenharmony_ci * in remote node. 4548c2ecf20Sopenharmony_ci */ 4558c2ecf20Sopenharmony_ci clear_bit(MD_RESYNCING_REMOTE, &mddev->recovery); 4568c2ecf20Sopenharmony_ci remove_suspend_info(mddev, slot); 4578c2ecf20Sopenharmony_ci set_bit(MD_RECOVERY_NEEDED, &mddev->recovery); 4588c2ecf20Sopenharmony_ci md_wakeup_thread(mddev->thread); 4598c2ecf20Sopenharmony_ci return; 4608c2ecf20Sopenharmony_ci } 4618c2ecf20Sopenharmony_ci 4628c2ecf20Sopenharmony_ci rdev_for_each(rdev, mddev) 4638c2ecf20Sopenharmony_ci if (rdev->raid_disk > -1 && !test_bit(Faulty, &rdev->flags)) { 4648c2ecf20Sopenharmony_ci sb = page_address(rdev->sb_page); 4658c2ecf20Sopenharmony_ci break; 4668c2ecf20Sopenharmony_ci } 4678c2ecf20Sopenharmony_ci 4688c2ecf20Sopenharmony_ci /* 4698c2ecf20Sopenharmony_ci * The bitmaps are not same for different nodes 4708c2ecf20Sopenharmony_ci * if RESYNCING is happening in one node, then 4718c2ecf20Sopenharmony_ci * the node which received the RESYNCING message 4728c2ecf20Sopenharmony_ci * probably will perform resync with the region 4738c2ecf20Sopenharmony_ci * [lo, hi] again, so we could reduce resync time 4748c2ecf20Sopenharmony_ci * a lot if we can ensure that the bitmaps among 4758c2ecf20Sopenharmony_ci * different nodes are match up well. 4768c2ecf20Sopenharmony_ci * 4778c2ecf20Sopenharmony_ci * sync_low/hi is used to record the region which 4788c2ecf20Sopenharmony_ci * arrived in the previous RESYNCING message, 4798c2ecf20Sopenharmony_ci * 4808c2ecf20Sopenharmony_ci * Call md_bitmap_sync_with_cluster to clear NEEDED_MASK 4818c2ecf20Sopenharmony_ci * and set RESYNC_MASK since resync thread is running 4828c2ecf20Sopenharmony_ci * in another node, so we don't need to do the resync 4838c2ecf20Sopenharmony_ci * again with the same section. 4848c2ecf20Sopenharmony_ci * 4858c2ecf20Sopenharmony_ci * Skip md_bitmap_sync_with_cluster in case reshape 4868c2ecf20Sopenharmony_ci * happening, because reshaping region is small and 4878c2ecf20Sopenharmony_ci * we don't want to trigger lots of WARN. 4888c2ecf20Sopenharmony_ci */ 4898c2ecf20Sopenharmony_ci if (sb && !(le32_to_cpu(sb->feature_map) & MD_FEATURE_RESHAPE_ACTIVE)) 4908c2ecf20Sopenharmony_ci md_bitmap_sync_with_cluster(mddev, cinfo->sync_low, 4918c2ecf20Sopenharmony_ci cinfo->sync_hi, lo, hi); 4928c2ecf20Sopenharmony_ci cinfo->sync_low = lo; 4938c2ecf20Sopenharmony_ci cinfo->sync_hi = hi; 4948c2ecf20Sopenharmony_ci 4958c2ecf20Sopenharmony_ci mddev->pers->quiesce(mddev, 1); 4968c2ecf20Sopenharmony_ci spin_lock_irq(&cinfo->suspend_lock); 4978c2ecf20Sopenharmony_ci cinfo->suspend_from = slot; 4988c2ecf20Sopenharmony_ci cinfo->suspend_lo = lo; 4998c2ecf20Sopenharmony_ci cinfo->suspend_hi = hi; 5008c2ecf20Sopenharmony_ci spin_unlock_irq(&cinfo->suspend_lock); 5018c2ecf20Sopenharmony_ci mddev->pers->quiesce(mddev, 0); 5028c2ecf20Sopenharmony_ci} 5038c2ecf20Sopenharmony_ci 5048c2ecf20Sopenharmony_cistatic void process_add_new_disk(struct mddev *mddev, struct cluster_msg *cmsg) 5058c2ecf20Sopenharmony_ci{ 5068c2ecf20Sopenharmony_ci char disk_uuid[64]; 5078c2ecf20Sopenharmony_ci struct md_cluster_info *cinfo = mddev->cluster_info; 5088c2ecf20Sopenharmony_ci char event_name[] = "EVENT=ADD_DEVICE"; 5098c2ecf20Sopenharmony_ci char raid_slot[16]; 5108c2ecf20Sopenharmony_ci char *envp[] = {event_name, disk_uuid, raid_slot, NULL}; 5118c2ecf20Sopenharmony_ci int len; 5128c2ecf20Sopenharmony_ci 5138c2ecf20Sopenharmony_ci len = snprintf(disk_uuid, 64, "DEVICE_UUID="); 5148c2ecf20Sopenharmony_ci sprintf(disk_uuid + len, "%pU", cmsg->uuid); 5158c2ecf20Sopenharmony_ci snprintf(raid_slot, 16, "RAID_DISK=%d", le32_to_cpu(cmsg->raid_slot)); 5168c2ecf20Sopenharmony_ci pr_info("%s:%d Sending kobject change with %s and %s\n", __func__, __LINE__, disk_uuid, raid_slot); 5178c2ecf20Sopenharmony_ci init_completion(&cinfo->newdisk_completion); 5188c2ecf20Sopenharmony_ci set_bit(MD_CLUSTER_WAITING_FOR_NEWDISK, &cinfo->state); 5198c2ecf20Sopenharmony_ci kobject_uevent_env(&disk_to_dev(mddev->gendisk)->kobj, KOBJ_CHANGE, envp); 5208c2ecf20Sopenharmony_ci wait_for_completion_timeout(&cinfo->newdisk_completion, 5218c2ecf20Sopenharmony_ci NEW_DEV_TIMEOUT); 5228c2ecf20Sopenharmony_ci clear_bit(MD_CLUSTER_WAITING_FOR_NEWDISK, &cinfo->state); 5238c2ecf20Sopenharmony_ci} 5248c2ecf20Sopenharmony_ci 5258c2ecf20Sopenharmony_ci 5268c2ecf20Sopenharmony_cistatic void process_metadata_update(struct mddev *mddev, struct cluster_msg *msg) 5278c2ecf20Sopenharmony_ci{ 5288c2ecf20Sopenharmony_ci int got_lock = 0; 5298c2ecf20Sopenharmony_ci struct md_cluster_info *cinfo = mddev->cluster_info; 5308c2ecf20Sopenharmony_ci mddev->good_device_nr = le32_to_cpu(msg->raid_slot); 5318c2ecf20Sopenharmony_ci 5328c2ecf20Sopenharmony_ci dlm_lock_sync(cinfo->no_new_dev_lockres, DLM_LOCK_CR); 5338c2ecf20Sopenharmony_ci wait_event(mddev->thread->wqueue, 5348c2ecf20Sopenharmony_ci (got_lock = mddev_trylock(mddev)) || 5358c2ecf20Sopenharmony_ci test_bit(MD_CLUSTER_HOLDING_MUTEX_FOR_RECVD, &cinfo->state)); 5368c2ecf20Sopenharmony_ci md_reload_sb(mddev, mddev->good_device_nr); 5378c2ecf20Sopenharmony_ci if (got_lock) 5388c2ecf20Sopenharmony_ci mddev_unlock(mddev); 5398c2ecf20Sopenharmony_ci} 5408c2ecf20Sopenharmony_ci 5418c2ecf20Sopenharmony_cistatic void process_remove_disk(struct mddev *mddev, struct cluster_msg *msg) 5428c2ecf20Sopenharmony_ci{ 5438c2ecf20Sopenharmony_ci struct md_rdev *rdev; 5448c2ecf20Sopenharmony_ci 5458c2ecf20Sopenharmony_ci rcu_read_lock(); 5468c2ecf20Sopenharmony_ci rdev = md_find_rdev_nr_rcu(mddev, le32_to_cpu(msg->raid_slot)); 5478c2ecf20Sopenharmony_ci if (rdev) { 5488c2ecf20Sopenharmony_ci set_bit(ClusterRemove, &rdev->flags); 5498c2ecf20Sopenharmony_ci set_bit(MD_RECOVERY_NEEDED, &mddev->recovery); 5508c2ecf20Sopenharmony_ci md_wakeup_thread(mddev->thread); 5518c2ecf20Sopenharmony_ci } 5528c2ecf20Sopenharmony_ci else 5538c2ecf20Sopenharmony_ci pr_warn("%s: %d Could not find disk(%d) to REMOVE\n", 5548c2ecf20Sopenharmony_ci __func__, __LINE__, le32_to_cpu(msg->raid_slot)); 5558c2ecf20Sopenharmony_ci rcu_read_unlock(); 5568c2ecf20Sopenharmony_ci} 5578c2ecf20Sopenharmony_ci 5588c2ecf20Sopenharmony_cistatic void process_readd_disk(struct mddev *mddev, struct cluster_msg *msg) 5598c2ecf20Sopenharmony_ci{ 5608c2ecf20Sopenharmony_ci struct md_rdev *rdev; 5618c2ecf20Sopenharmony_ci 5628c2ecf20Sopenharmony_ci rcu_read_lock(); 5638c2ecf20Sopenharmony_ci rdev = md_find_rdev_nr_rcu(mddev, le32_to_cpu(msg->raid_slot)); 5648c2ecf20Sopenharmony_ci if (rdev && test_bit(Faulty, &rdev->flags)) 5658c2ecf20Sopenharmony_ci clear_bit(Faulty, &rdev->flags); 5668c2ecf20Sopenharmony_ci else 5678c2ecf20Sopenharmony_ci pr_warn("%s: %d Could not find disk(%d) which is faulty", 5688c2ecf20Sopenharmony_ci __func__, __LINE__, le32_to_cpu(msg->raid_slot)); 5698c2ecf20Sopenharmony_ci rcu_read_unlock(); 5708c2ecf20Sopenharmony_ci} 5718c2ecf20Sopenharmony_ci 5728c2ecf20Sopenharmony_cistatic int process_recvd_msg(struct mddev *mddev, struct cluster_msg *msg) 5738c2ecf20Sopenharmony_ci{ 5748c2ecf20Sopenharmony_ci int ret = 0; 5758c2ecf20Sopenharmony_ci 5768c2ecf20Sopenharmony_ci if (WARN(mddev->cluster_info->slot_number - 1 == le32_to_cpu(msg->slot), 5778c2ecf20Sopenharmony_ci "node %d received it's own msg\n", le32_to_cpu(msg->slot))) 5788c2ecf20Sopenharmony_ci return -1; 5798c2ecf20Sopenharmony_ci switch (le32_to_cpu(msg->type)) { 5808c2ecf20Sopenharmony_ci case METADATA_UPDATED: 5818c2ecf20Sopenharmony_ci process_metadata_update(mddev, msg); 5828c2ecf20Sopenharmony_ci break; 5838c2ecf20Sopenharmony_ci case CHANGE_CAPACITY: 5848c2ecf20Sopenharmony_ci set_capacity(mddev->gendisk, mddev->array_sectors); 5858c2ecf20Sopenharmony_ci revalidate_disk_size(mddev->gendisk, true); 5868c2ecf20Sopenharmony_ci break; 5878c2ecf20Sopenharmony_ci case RESYNCING: 5888c2ecf20Sopenharmony_ci set_bit(MD_RESYNCING_REMOTE, &mddev->recovery); 5898c2ecf20Sopenharmony_ci process_suspend_info(mddev, le32_to_cpu(msg->slot), 5908c2ecf20Sopenharmony_ci le64_to_cpu(msg->low), 5918c2ecf20Sopenharmony_ci le64_to_cpu(msg->high)); 5928c2ecf20Sopenharmony_ci break; 5938c2ecf20Sopenharmony_ci case NEWDISK: 5948c2ecf20Sopenharmony_ci process_add_new_disk(mddev, msg); 5958c2ecf20Sopenharmony_ci break; 5968c2ecf20Sopenharmony_ci case REMOVE: 5978c2ecf20Sopenharmony_ci process_remove_disk(mddev, msg); 5988c2ecf20Sopenharmony_ci break; 5998c2ecf20Sopenharmony_ci case RE_ADD: 6008c2ecf20Sopenharmony_ci process_readd_disk(mddev, msg); 6018c2ecf20Sopenharmony_ci break; 6028c2ecf20Sopenharmony_ci case BITMAP_NEEDS_SYNC: 6038c2ecf20Sopenharmony_ci __recover_slot(mddev, le32_to_cpu(msg->slot)); 6048c2ecf20Sopenharmony_ci break; 6058c2ecf20Sopenharmony_ci case BITMAP_RESIZE: 6068c2ecf20Sopenharmony_ci if (le64_to_cpu(msg->high) != mddev->pers->size(mddev, 0, 0)) 6078c2ecf20Sopenharmony_ci ret = md_bitmap_resize(mddev->bitmap, 6088c2ecf20Sopenharmony_ci le64_to_cpu(msg->high), 0, 0); 6098c2ecf20Sopenharmony_ci break; 6108c2ecf20Sopenharmony_ci default: 6118c2ecf20Sopenharmony_ci ret = -1; 6128c2ecf20Sopenharmony_ci pr_warn("%s:%d Received unknown message from %d\n", 6138c2ecf20Sopenharmony_ci __func__, __LINE__, msg->slot); 6148c2ecf20Sopenharmony_ci } 6158c2ecf20Sopenharmony_ci return ret; 6168c2ecf20Sopenharmony_ci} 6178c2ecf20Sopenharmony_ci 6188c2ecf20Sopenharmony_ci/* 6198c2ecf20Sopenharmony_ci * thread for receiving message 6208c2ecf20Sopenharmony_ci */ 6218c2ecf20Sopenharmony_cistatic void recv_daemon(struct md_thread *thread) 6228c2ecf20Sopenharmony_ci{ 6238c2ecf20Sopenharmony_ci struct md_cluster_info *cinfo = thread->mddev->cluster_info; 6248c2ecf20Sopenharmony_ci struct dlm_lock_resource *ack_lockres = cinfo->ack_lockres; 6258c2ecf20Sopenharmony_ci struct dlm_lock_resource *message_lockres = cinfo->message_lockres; 6268c2ecf20Sopenharmony_ci struct cluster_msg msg; 6278c2ecf20Sopenharmony_ci int ret; 6288c2ecf20Sopenharmony_ci 6298c2ecf20Sopenharmony_ci mutex_lock(&cinfo->recv_mutex); 6308c2ecf20Sopenharmony_ci /*get CR on Message*/ 6318c2ecf20Sopenharmony_ci if (dlm_lock_sync(message_lockres, DLM_LOCK_CR)) { 6328c2ecf20Sopenharmony_ci pr_err("md/raid1:failed to get CR on MESSAGE\n"); 6338c2ecf20Sopenharmony_ci mutex_unlock(&cinfo->recv_mutex); 6348c2ecf20Sopenharmony_ci return; 6358c2ecf20Sopenharmony_ci } 6368c2ecf20Sopenharmony_ci 6378c2ecf20Sopenharmony_ci /* read lvb and wake up thread to process this message_lockres */ 6388c2ecf20Sopenharmony_ci memcpy(&msg, message_lockres->lksb.sb_lvbptr, sizeof(struct cluster_msg)); 6398c2ecf20Sopenharmony_ci ret = process_recvd_msg(thread->mddev, &msg); 6408c2ecf20Sopenharmony_ci if (ret) 6418c2ecf20Sopenharmony_ci goto out; 6428c2ecf20Sopenharmony_ci 6438c2ecf20Sopenharmony_ci /*release CR on ack_lockres*/ 6448c2ecf20Sopenharmony_ci ret = dlm_unlock_sync(ack_lockres); 6458c2ecf20Sopenharmony_ci if (unlikely(ret != 0)) 6468c2ecf20Sopenharmony_ci pr_info("unlock ack failed return %d\n", ret); 6478c2ecf20Sopenharmony_ci /*up-convert to PR on message_lockres*/ 6488c2ecf20Sopenharmony_ci ret = dlm_lock_sync(message_lockres, DLM_LOCK_PR); 6498c2ecf20Sopenharmony_ci if (unlikely(ret != 0)) 6508c2ecf20Sopenharmony_ci pr_info("lock PR on msg failed return %d\n", ret); 6518c2ecf20Sopenharmony_ci /*get CR on ack_lockres again*/ 6528c2ecf20Sopenharmony_ci ret = dlm_lock_sync(ack_lockres, DLM_LOCK_CR); 6538c2ecf20Sopenharmony_ci if (unlikely(ret != 0)) 6548c2ecf20Sopenharmony_ci pr_info("lock CR on ack failed return %d\n", ret); 6558c2ecf20Sopenharmony_ciout: 6568c2ecf20Sopenharmony_ci /*release CR on message_lockres*/ 6578c2ecf20Sopenharmony_ci ret = dlm_unlock_sync(message_lockres); 6588c2ecf20Sopenharmony_ci if (unlikely(ret != 0)) 6598c2ecf20Sopenharmony_ci pr_info("unlock msg failed return %d\n", ret); 6608c2ecf20Sopenharmony_ci mutex_unlock(&cinfo->recv_mutex); 6618c2ecf20Sopenharmony_ci} 6628c2ecf20Sopenharmony_ci 6638c2ecf20Sopenharmony_ci/* lock_token() 6648c2ecf20Sopenharmony_ci * Takes the lock on the TOKEN lock resource so no other 6658c2ecf20Sopenharmony_ci * node can communicate while the operation is underway. 6668c2ecf20Sopenharmony_ci */ 6678c2ecf20Sopenharmony_cistatic int lock_token(struct md_cluster_info *cinfo) 6688c2ecf20Sopenharmony_ci{ 6698c2ecf20Sopenharmony_ci int error; 6708c2ecf20Sopenharmony_ci 6718c2ecf20Sopenharmony_ci error = dlm_lock_sync(cinfo->token_lockres, DLM_LOCK_EX); 6728c2ecf20Sopenharmony_ci if (error) { 6738c2ecf20Sopenharmony_ci pr_err("md-cluster(%s:%d): failed to get EX on TOKEN (%d)\n", 6748c2ecf20Sopenharmony_ci __func__, __LINE__, error); 6758c2ecf20Sopenharmony_ci } else { 6768c2ecf20Sopenharmony_ci /* Lock the receive sequence */ 6778c2ecf20Sopenharmony_ci mutex_lock(&cinfo->recv_mutex); 6788c2ecf20Sopenharmony_ci } 6798c2ecf20Sopenharmony_ci return error; 6808c2ecf20Sopenharmony_ci} 6818c2ecf20Sopenharmony_ci 6828c2ecf20Sopenharmony_ci/* lock_comm() 6838c2ecf20Sopenharmony_ci * Sets the MD_CLUSTER_SEND_LOCK bit to lock the send channel. 6848c2ecf20Sopenharmony_ci */ 6858c2ecf20Sopenharmony_cistatic int lock_comm(struct md_cluster_info *cinfo, bool mddev_locked) 6868c2ecf20Sopenharmony_ci{ 6878c2ecf20Sopenharmony_ci int rv, set_bit = 0; 6888c2ecf20Sopenharmony_ci struct mddev *mddev = cinfo->mddev; 6898c2ecf20Sopenharmony_ci 6908c2ecf20Sopenharmony_ci /* 6918c2ecf20Sopenharmony_ci * If resync thread run after raid1d thread, then process_metadata_update 6928c2ecf20Sopenharmony_ci * could not continue if raid1d held reconfig_mutex (and raid1d is blocked 6938c2ecf20Sopenharmony_ci * since another node already got EX on Token and waitting the EX of Ack), 6948c2ecf20Sopenharmony_ci * so let resync wake up thread in case flag is set. 6958c2ecf20Sopenharmony_ci */ 6968c2ecf20Sopenharmony_ci if (mddev_locked && !test_bit(MD_CLUSTER_HOLDING_MUTEX_FOR_RECVD, 6978c2ecf20Sopenharmony_ci &cinfo->state)) { 6988c2ecf20Sopenharmony_ci rv = test_and_set_bit_lock(MD_CLUSTER_HOLDING_MUTEX_FOR_RECVD, 6998c2ecf20Sopenharmony_ci &cinfo->state); 7008c2ecf20Sopenharmony_ci WARN_ON_ONCE(rv); 7018c2ecf20Sopenharmony_ci md_wakeup_thread(mddev->thread); 7028c2ecf20Sopenharmony_ci set_bit = 1; 7038c2ecf20Sopenharmony_ci } 7048c2ecf20Sopenharmony_ci 7058c2ecf20Sopenharmony_ci wait_event(cinfo->wait, 7068c2ecf20Sopenharmony_ci !test_and_set_bit(MD_CLUSTER_SEND_LOCK, &cinfo->state)); 7078c2ecf20Sopenharmony_ci rv = lock_token(cinfo); 7088c2ecf20Sopenharmony_ci if (set_bit) 7098c2ecf20Sopenharmony_ci clear_bit_unlock(MD_CLUSTER_HOLDING_MUTEX_FOR_RECVD, &cinfo->state); 7108c2ecf20Sopenharmony_ci return rv; 7118c2ecf20Sopenharmony_ci} 7128c2ecf20Sopenharmony_ci 7138c2ecf20Sopenharmony_cistatic void unlock_comm(struct md_cluster_info *cinfo) 7148c2ecf20Sopenharmony_ci{ 7158c2ecf20Sopenharmony_ci WARN_ON(cinfo->token_lockres->mode != DLM_LOCK_EX); 7168c2ecf20Sopenharmony_ci mutex_unlock(&cinfo->recv_mutex); 7178c2ecf20Sopenharmony_ci dlm_unlock_sync(cinfo->token_lockres); 7188c2ecf20Sopenharmony_ci clear_bit(MD_CLUSTER_SEND_LOCK, &cinfo->state); 7198c2ecf20Sopenharmony_ci wake_up(&cinfo->wait); 7208c2ecf20Sopenharmony_ci} 7218c2ecf20Sopenharmony_ci 7228c2ecf20Sopenharmony_ci/* __sendmsg() 7238c2ecf20Sopenharmony_ci * This function performs the actual sending of the message. This function is 7248c2ecf20Sopenharmony_ci * usually called after performing the encompassing operation 7258c2ecf20Sopenharmony_ci * The function: 7268c2ecf20Sopenharmony_ci * 1. Grabs the message lockresource in EX mode 7278c2ecf20Sopenharmony_ci * 2. Copies the message to the message LVB 7288c2ecf20Sopenharmony_ci * 3. Downconverts message lockresource to CW 7298c2ecf20Sopenharmony_ci * 4. Upconverts ack lock resource from CR to EX. This forces the BAST on other nodes 7308c2ecf20Sopenharmony_ci * and the other nodes read the message. The thread will wait here until all other 7318c2ecf20Sopenharmony_ci * nodes have released ack lock resource. 7328c2ecf20Sopenharmony_ci * 5. Downconvert ack lockresource to CR 7338c2ecf20Sopenharmony_ci */ 7348c2ecf20Sopenharmony_cistatic int __sendmsg(struct md_cluster_info *cinfo, struct cluster_msg *cmsg) 7358c2ecf20Sopenharmony_ci{ 7368c2ecf20Sopenharmony_ci int error; 7378c2ecf20Sopenharmony_ci int slot = cinfo->slot_number - 1; 7388c2ecf20Sopenharmony_ci 7398c2ecf20Sopenharmony_ci cmsg->slot = cpu_to_le32(slot); 7408c2ecf20Sopenharmony_ci /*get EX on Message*/ 7418c2ecf20Sopenharmony_ci error = dlm_lock_sync(cinfo->message_lockres, DLM_LOCK_EX); 7428c2ecf20Sopenharmony_ci if (error) { 7438c2ecf20Sopenharmony_ci pr_err("md-cluster: failed to get EX on MESSAGE (%d)\n", error); 7448c2ecf20Sopenharmony_ci goto failed_message; 7458c2ecf20Sopenharmony_ci } 7468c2ecf20Sopenharmony_ci 7478c2ecf20Sopenharmony_ci memcpy(cinfo->message_lockres->lksb.sb_lvbptr, (void *)cmsg, 7488c2ecf20Sopenharmony_ci sizeof(struct cluster_msg)); 7498c2ecf20Sopenharmony_ci /*down-convert EX to CW on Message*/ 7508c2ecf20Sopenharmony_ci error = dlm_lock_sync(cinfo->message_lockres, DLM_LOCK_CW); 7518c2ecf20Sopenharmony_ci if (error) { 7528c2ecf20Sopenharmony_ci pr_err("md-cluster: failed to convert EX to CW on MESSAGE(%d)\n", 7538c2ecf20Sopenharmony_ci error); 7548c2ecf20Sopenharmony_ci goto failed_ack; 7558c2ecf20Sopenharmony_ci } 7568c2ecf20Sopenharmony_ci 7578c2ecf20Sopenharmony_ci /*up-convert CR to EX on Ack*/ 7588c2ecf20Sopenharmony_ci error = dlm_lock_sync(cinfo->ack_lockres, DLM_LOCK_EX); 7598c2ecf20Sopenharmony_ci if (error) { 7608c2ecf20Sopenharmony_ci pr_err("md-cluster: failed to convert CR to EX on ACK(%d)\n", 7618c2ecf20Sopenharmony_ci error); 7628c2ecf20Sopenharmony_ci goto failed_ack; 7638c2ecf20Sopenharmony_ci } 7648c2ecf20Sopenharmony_ci 7658c2ecf20Sopenharmony_ci /*down-convert EX to CR on Ack*/ 7668c2ecf20Sopenharmony_ci error = dlm_lock_sync(cinfo->ack_lockres, DLM_LOCK_CR); 7678c2ecf20Sopenharmony_ci if (error) { 7688c2ecf20Sopenharmony_ci pr_err("md-cluster: failed to convert EX to CR on ACK(%d)\n", 7698c2ecf20Sopenharmony_ci error); 7708c2ecf20Sopenharmony_ci goto failed_ack; 7718c2ecf20Sopenharmony_ci } 7728c2ecf20Sopenharmony_ci 7738c2ecf20Sopenharmony_cifailed_ack: 7748c2ecf20Sopenharmony_ci error = dlm_unlock_sync(cinfo->message_lockres); 7758c2ecf20Sopenharmony_ci if (unlikely(error != 0)) { 7768c2ecf20Sopenharmony_ci pr_err("md-cluster: failed convert to NL on MESSAGE(%d)\n", 7778c2ecf20Sopenharmony_ci error); 7788c2ecf20Sopenharmony_ci /* in case the message can't be released due to some reason */ 7798c2ecf20Sopenharmony_ci goto failed_ack; 7808c2ecf20Sopenharmony_ci } 7818c2ecf20Sopenharmony_cifailed_message: 7828c2ecf20Sopenharmony_ci return error; 7838c2ecf20Sopenharmony_ci} 7848c2ecf20Sopenharmony_ci 7858c2ecf20Sopenharmony_cistatic int sendmsg(struct md_cluster_info *cinfo, struct cluster_msg *cmsg, 7868c2ecf20Sopenharmony_ci bool mddev_locked) 7878c2ecf20Sopenharmony_ci{ 7888c2ecf20Sopenharmony_ci int ret; 7898c2ecf20Sopenharmony_ci 7908c2ecf20Sopenharmony_ci ret = lock_comm(cinfo, mddev_locked); 7918c2ecf20Sopenharmony_ci if (!ret) { 7928c2ecf20Sopenharmony_ci ret = __sendmsg(cinfo, cmsg); 7938c2ecf20Sopenharmony_ci unlock_comm(cinfo); 7948c2ecf20Sopenharmony_ci } 7958c2ecf20Sopenharmony_ci return ret; 7968c2ecf20Sopenharmony_ci} 7978c2ecf20Sopenharmony_ci 7988c2ecf20Sopenharmony_cistatic int gather_all_resync_info(struct mddev *mddev, int total_slots) 7998c2ecf20Sopenharmony_ci{ 8008c2ecf20Sopenharmony_ci struct md_cluster_info *cinfo = mddev->cluster_info; 8018c2ecf20Sopenharmony_ci int i, ret = 0; 8028c2ecf20Sopenharmony_ci struct dlm_lock_resource *bm_lockres; 8038c2ecf20Sopenharmony_ci char str[64]; 8048c2ecf20Sopenharmony_ci sector_t lo, hi; 8058c2ecf20Sopenharmony_ci 8068c2ecf20Sopenharmony_ci 8078c2ecf20Sopenharmony_ci for (i = 0; i < total_slots; i++) { 8088c2ecf20Sopenharmony_ci memset(str, '\0', 64); 8098c2ecf20Sopenharmony_ci snprintf(str, 64, "bitmap%04d", i); 8108c2ecf20Sopenharmony_ci bm_lockres = lockres_init(mddev, str, NULL, 1); 8118c2ecf20Sopenharmony_ci if (!bm_lockres) 8128c2ecf20Sopenharmony_ci return -ENOMEM; 8138c2ecf20Sopenharmony_ci if (i == (cinfo->slot_number - 1)) { 8148c2ecf20Sopenharmony_ci lockres_free(bm_lockres); 8158c2ecf20Sopenharmony_ci continue; 8168c2ecf20Sopenharmony_ci } 8178c2ecf20Sopenharmony_ci 8188c2ecf20Sopenharmony_ci bm_lockres->flags |= DLM_LKF_NOQUEUE; 8198c2ecf20Sopenharmony_ci ret = dlm_lock_sync(bm_lockres, DLM_LOCK_PW); 8208c2ecf20Sopenharmony_ci if (ret == -EAGAIN) { 8218c2ecf20Sopenharmony_ci if (read_resync_info(mddev, bm_lockres)) { 8228c2ecf20Sopenharmony_ci pr_info("%s:%d Resync[%llu..%llu] in progress on %d\n", 8238c2ecf20Sopenharmony_ci __func__, __LINE__, 8248c2ecf20Sopenharmony_ci (unsigned long long) cinfo->suspend_lo, 8258c2ecf20Sopenharmony_ci (unsigned long long) cinfo->suspend_hi, 8268c2ecf20Sopenharmony_ci i); 8278c2ecf20Sopenharmony_ci cinfo->suspend_from = i; 8288c2ecf20Sopenharmony_ci } 8298c2ecf20Sopenharmony_ci ret = 0; 8308c2ecf20Sopenharmony_ci lockres_free(bm_lockres); 8318c2ecf20Sopenharmony_ci continue; 8328c2ecf20Sopenharmony_ci } 8338c2ecf20Sopenharmony_ci if (ret) { 8348c2ecf20Sopenharmony_ci lockres_free(bm_lockres); 8358c2ecf20Sopenharmony_ci goto out; 8368c2ecf20Sopenharmony_ci } 8378c2ecf20Sopenharmony_ci 8388c2ecf20Sopenharmony_ci /* Read the disk bitmap sb and check if it needs recovery */ 8398c2ecf20Sopenharmony_ci ret = md_bitmap_copy_from_slot(mddev, i, &lo, &hi, false); 8408c2ecf20Sopenharmony_ci if (ret) { 8418c2ecf20Sopenharmony_ci pr_warn("md-cluster: Could not gather bitmaps from slot %d", i); 8428c2ecf20Sopenharmony_ci lockres_free(bm_lockres); 8438c2ecf20Sopenharmony_ci continue; 8448c2ecf20Sopenharmony_ci } 8458c2ecf20Sopenharmony_ci if ((hi > 0) && (lo < mddev->recovery_cp)) { 8468c2ecf20Sopenharmony_ci set_bit(MD_RECOVERY_NEEDED, &mddev->recovery); 8478c2ecf20Sopenharmony_ci mddev->recovery_cp = lo; 8488c2ecf20Sopenharmony_ci md_check_recovery(mddev); 8498c2ecf20Sopenharmony_ci } 8508c2ecf20Sopenharmony_ci 8518c2ecf20Sopenharmony_ci lockres_free(bm_lockres); 8528c2ecf20Sopenharmony_ci } 8538c2ecf20Sopenharmony_ciout: 8548c2ecf20Sopenharmony_ci return ret; 8558c2ecf20Sopenharmony_ci} 8568c2ecf20Sopenharmony_ci 8578c2ecf20Sopenharmony_cistatic int join(struct mddev *mddev, int nodes) 8588c2ecf20Sopenharmony_ci{ 8598c2ecf20Sopenharmony_ci struct md_cluster_info *cinfo; 8608c2ecf20Sopenharmony_ci int ret, ops_rv; 8618c2ecf20Sopenharmony_ci char str[64]; 8628c2ecf20Sopenharmony_ci 8638c2ecf20Sopenharmony_ci cinfo = kzalloc(sizeof(struct md_cluster_info), GFP_KERNEL); 8648c2ecf20Sopenharmony_ci if (!cinfo) 8658c2ecf20Sopenharmony_ci return -ENOMEM; 8668c2ecf20Sopenharmony_ci 8678c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&cinfo->suspend_list); 8688c2ecf20Sopenharmony_ci spin_lock_init(&cinfo->suspend_lock); 8698c2ecf20Sopenharmony_ci init_completion(&cinfo->completion); 8708c2ecf20Sopenharmony_ci set_bit(MD_CLUSTER_BEGIN_JOIN_CLUSTER, &cinfo->state); 8718c2ecf20Sopenharmony_ci init_waitqueue_head(&cinfo->wait); 8728c2ecf20Sopenharmony_ci mutex_init(&cinfo->recv_mutex); 8738c2ecf20Sopenharmony_ci 8748c2ecf20Sopenharmony_ci mddev->cluster_info = cinfo; 8758c2ecf20Sopenharmony_ci cinfo->mddev = mddev; 8768c2ecf20Sopenharmony_ci 8778c2ecf20Sopenharmony_ci memset(str, 0, 64); 8788c2ecf20Sopenharmony_ci sprintf(str, "%pU", mddev->uuid); 8798c2ecf20Sopenharmony_ci ret = dlm_new_lockspace(str, mddev->bitmap_info.cluster_name, 8808c2ecf20Sopenharmony_ci DLM_LSFL_FS, LVB_SIZE, 8818c2ecf20Sopenharmony_ci &md_ls_ops, mddev, &ops_rv, &cinfo->lockspace); 8828c2ecf20Sopenharmony_ci if (ret) 8838c2ecf20Sopenharmony_ci goto err; 8848c2ecf20Sopenharmony_ci wait_for_completion(&cinfo->completion); 8858c2ecf20Sopenharmony_ci if (nodes < cinfo->slot_number) { 8868c2ecf20Sopenharmony_ci pr_err("md-cluster: Slot allotted(%d) is greater than available slots(%d).", 8878c2ecf20Sopenharmony_ci cinfo->slot_number, nodes); 8888c2ecf20Sopenharmony_ci ret = -ERANGE; 8898c2ecf20Sopenharmony_ci goto err; 8908c2ecf20Sopenharmony_ci } 8918c2ecf20Sopenharmony_ci /* Initiate the communication resources */ 8928c2ecf20Sopenharmony_ci ret = -ENOMEM; 8938c2ecf20Sopenharmony_ci cinfo->recv_thread = md_register_thread(recv_daemon, mddev, "cluster_recv"); 8948c2ecf20Sopenharmony_ci if (!cinfo->recv_thread) { 8958c2ecf20Sopenharmony_ci pr_err("md-cluster: cannot allocate memory for recv_thread!\n"); 8968c2ecf20Sopenharmony_ci goto err; 8978c2ecf20Sopenharmony_ci } 8988c2ecf20Sopenharmony_ci cinfo->message_lockres = lockres_init(mddev, "message", NULL, 1); 8998c2ecf20Sopenharmony_ci if (!cinfo->message_lockres) 9008c2ecf20Sopenharmony_ci goto err; 9018c2ecf20Sopenharmony_ci cinfo->token_lockres = lockres_init(mddev, "token", NULL, 0); 9028c2ecf20Sopenharmony_ci if (!cinfo->token_lockres) 9038c2ecf20Sopenharmony_ci goto err; 9048c2ecf20Sopenharmony_ci cinfo->no_new_dev_lockres = lockres_init(mddev, "no-new-dev", NULL, 0); 9058c2ecf20Sopenharmony_ci if (!cinfo->no_new_dev_lockres) 9068c2ecf20Sopenharmony_ci goto err; 9078c2ecf20Sopenharmony_ci 9088c2ecf20Sopenharmony_ci ret = dlm_lock_sync(cinfo->token_lockres, DLM_LOCK_EX); 9098c2ecf20Sopenharmony_ci if (ret) { 9108c2ecf20Sopenharmony_ci ret = -EAGAIN; 9118c2ecf20Sopenharmony_ci pr_err("md-cluster: can't join cluster to avoid lock issue\n"); 9128c2ecf20Sopenharmony_ci goto err; 9138c2ecf20Sopenharmony_ci } 9148c2ecf20Sopenharmony_ci cinfo->ack_lockres = lockres_init(mddev, "ack", ack_bast, 0); 9158c2ecf20Sopenharmony_ci if (!cinfo->ack_lockres) { 9168c2ecf20Sopenharmony_ci ret = -ENOMEM; 9178c2ecf20Sopenharmony_ci goto err; 9188c2ecf20Sopenharmony_ci } 9198c2ecf20Sopenharmony_ci /* get sync CR lock on ACK. */ 9208c2ecf20Sopenharmony_ci if (dlm_lock_sync(cinfo->ack_lockres, DLM_LOCK_CR)) 9218c2ecf20Sopenharmony_ci pr_err("md-cluster: failed to get a sync CR lock on ACK!(%d)\n", 9228c2ecf20Sopenharmony_ci ret); 9238c2ecf20Sopenharmony_ci dlm_unlock_sync(cinfo->token_lockres); 9248c2ecf20Sopenharmony_ci /* get sync CR lock on no-new-dev. */ 9258c2ecf20Sopenharmony_ci if (dlm_lock_sync(cinfo->no_new_dev_lockres, DLM_LOCK_CR)) 9268c2ecf20Sopenharmony_ci pr_err("md-cluster: failed to get a sync CR lock on no-new-dev!(%d)\n", ret); 9278c2ecf20Sopenharmony_ci 9288c2ecf20Sopenharmony_ci 9298c2ecf20Sopenharmony_ci pr_info("md-cluster: Joined cluster %s slot %d\n", str, cinfo->slot_number); 9308c2ecf20Sopenharmony_ci snprintf(str, 64, "bitmap%04d", cinfo->slot_number - 1); 9318c2ecf20Sopenharmony_ci cinfo->bitmap_lockres = lockres_init(mddev, str, NULL, 1); 9328c2ecf20Sopenharmony_ci if (!cinfo->bitmap_lockres) { 9338c2ecf20Sopenharmony_ci ret = -ENOMEM; 9348c2ecf20Sopenharmony_ci goto err; 9358c2ecf20Sopenharmony_ci } 9368c2ecf20Sopenharmony_ci if (dlm_lock_sync(cinfo->bitmap_lockres, DLM_LOCK_PW)) { 9378c2ecf20Sopenharmony_ci pr_err("Failed to get bitmap lock\n"); 9388c2ecf20Sopenharmony_ci ret = -EINVAL; 9398c2ecf20Sopenharmony_ci goto err; 9408c2ecf20Sopenharmony_ci } 9418c2ecf20Sopenharmony_ci 9428c2ecf20Sopenharmony_ci cinfo->resync_lockres = lockres_init(mddev, "resync", NULL, 0); 9438c2ecf20Sopenharmony_ci if (!cinfo->resync_lockres) { 9448c2ecf20Sopenharmony_ci ret = -ENOMEM; 9458c2ecf20Sopenharmony_ci goto err; 9468c2ecf20Sopenharmony_ci } 9478c2ecf20Sopenharmony_ci 9488c2ecf20Sopenharmony_ci return 0; 9498c2ecf20Sopenharmony_cierr: 9508c2ecf20Sopenharmony_ci set_bit(MD_CLUSTER_HOLDING_MUTEX_FOR_RECVD, &cinfo->state); 9518c2ecf20Sopenharmony_ci md_unregister_thread(&cinfo->recovery_thread); 9528c2ecf20Sopenharmony_ci md_unregister_thread(&cinfo->recv_thread); 9538c2ecf20Sopenharmony_ci lockres_free(cinfo->message_lockres); 9548c2ecf20Sopenharmony_ci lockres_free(cinfo->token_lockres); 9558c2ecf20Sopenharmony_ci lockres_free(cinfo->ack_lockres); 9568c2ecf20Sopenharmony_ci lockres_free(cinfo->no_new_dev_lockres); 9578c2ecf20Sopenharmony_ci lockres_free(cinfo->resync_lockres); 9588c2ecf20Sopenharmony_ci lockres_free(cinfo->bitmap_lockres); 9598c2ecf20Sopenharmony_ci if (cinfo->lockspace) 9608c2ecf20Sopenharmony_ci dlm_release_lockspace(cinfo->lockspace, 2); 9618c2ecf20Sopenharmony_ci mddev->cluster_info = NULL; 9628c2ecf20Sopenharmony_ci kfree(cinfo); 9638c2ecf20Sopenharmony_ci return ret; 9648c2ecf20Sopenharmony_ci} 9658c2ecf20Sopenharmony_ci 9668c2ecf20Sopenharmony_cistatic void load_bitmaps(struct mddev *mddev, int total_slots) 9678c2ecf20Sopenharmony_ci{ 9688c2ecf20Sopenharmony_ci struct md_cluster_info *cinfo = mddev->cluster_info; 9698c2ecf20Sopenharmony_ci 9708c2ecf20Sopenharmony_ci /* load all the node's bitmap info for resync */ 9718c2ecf20Sopenharmony_ci if (gather_all_resync_info(mddev, total_slots)) 9728c2ecf20Sopenharmony_ci pr_err("md-cluster: failed to gather all resyn infos\n"); 9738c2ecf20Sopenharmony_ci set_bit(MD_CLUSTER_ALREADY_IN_CLUSTER, &cinfo->state); 9748c2ecf20Sopenharmony_ci /* wake up recv thread in case something need to be handled */ 9758c2ecf20Sopenharmony_ci if (test_and_clear_bit(MD_CLUSTER_PENDING_RECV_EVENT, &cinfo->state)) 9768c2ecf20Sopenharmony_ci md_wakeup_thread(cinfo->recv_thread); 9778c2ecf20Sopenharmony_ci} 9788c2ecf20Sopenharmony_ci 9798c2ecf20Sopenharmony_cistatic void resync_bitmap(struct mddev *mddev) 9808c2ecf20Sopenharmony_ci{ 9818c2ecf20Sopenharmony_ci struct md_cluster_info *cinfo = mddev->cluster_info; 9828c2ecf20Sopenharmony_ci struct cluster_msg cmsg = {0}; 9838c2ecf20Sopenharmony_ci int err; 9848c2ecf20Sopenharmony_ci 9858c2ecf20Sopenharmony_ci cmsg.type = cpu_to_le32(BITMAP_NEEDS_SYNC); 9868c2ecf20Sopenharmony_ci err = sendmsg(cinfo, &cmsg, 1); 9878c2ecf20Sopenharmony_ci if (err) 9888c2ecf20Sopenharmony_ci pr_err("%s:%d: failed to send BITMAP_NEEDS_SYNC message (%d)\n", 9898c2ecf20Sopenharmony_ci __func__, __LINE__, err); 9908c2ecf20Sopenharmony_ci} 9918c2ecf20Sopenharmony_ci 9928c2ecf20Sopenharmony_cistatic void unlock_all_bitmaps(struct mddev *mddev); 9938c2ecf20Sopenharmony_cistatic int leave(struct mddev *mddev) 9948c2ecf20Sopenharmony_ci{ 9958c2ecf20Sopenharmony_ci struct md_cluster_info *cinfo = mddev->cluster_info; 9968c2ecf20Sopenharmony_ci 9978c2ecf20Sopenharmony_ci if (!cinfo) 9988c2ecf20Sopenharmony_ci return 0; 9998c2ecf20Sopenharmony_ci 10008c2ecf20Sopenharmony_ci /* 10018c2ecf20Sopenharmony_ci * BITMAP_NEEDS_SYNC message should be sent when node 10028c2ecf20Sopenharmony_ci * is leaving the cluster with dirty bitmap, also we 10038c2ecf20Sopenharmony_ci * can only deliver it when dlm connection is available. 10048c2ecf20Sopenharmony_ci * 10058c2ecf20Sopenharmony_ci * Also, we should send BITMAP_NEEDS_SYNC message in 10068c2ecf20Sopenharmony_ci * case reshaping is interrupted. 10078c2ecf20Sopenharmony_ci */ 10088c2ecf20Sopenharmony_ci if ((cinfo->slot_number > 0 && mddev->recovery_cp != MaxSector) || 10098c2ecf20Sopenharmony_ci (mddev->reshape_position != MaxSector && 10108c2ecf20Sopenharmony_ci test_bit(MD_CLOSING, &mddev->flags))) 10118c2ecf20Sopenharmony_ci resync_bitmap(mddev); 10128c2ecf20Sopenharmony_ci 10138c2ecf20Sopenharmony_ci set_bit(MD_CLUSTER_HOLDING_MUTEX_FOR_RECVD, &cinfo->state); 10148c2ecf20Sopenharmony_ci md_unregister_thread(&cinfo->recovery_thread); 10158c2ecf20Sopenharmony_ci md_unregister_thread(&cinfo->recv_thread); 10168c2ecf20Sopenharmony_ci lockres_free(cinfo->message_lockres); 10178c2ecf20Sopenharmony_ci lockres_free(cinfo->token_lockres); 10188c2ecf20Sopenharmony_ci lockres_free(cinfo->ack_lockres); 10198c2ecf20Sopenharmony_ci lockres_free(cinfo->no_new_dev_lockres); 10208c2ecf20Sopenharmony_ci lockres_free(cinfo->resync_lockres); 10218c2ecf20Sopenharmony_ci lockres_free(cinfo->bitmap_lockres); 10228c2ecf20Sopenharmony_ci unlock_all_bitmaps(mddev); 10238c2ecf20Sopenharmony_ci dlm_release_lockspace(cinfo->lockspace, 2); 10248c2ecf20Sopenharmony_ci kfree(cinfo); 10258c2ecf20Sopenharmony_ci return 0; 10268c2ecf20Sopenharmony_ci} 10278c2ecf20Sopenharmony_ci 10288c2ecf20Sopenharmony_ci/* slot_number(): Returns the MD slot number to use 10298c2ecf20Sopenharmony_ci * DLM starts the slot numbers from 1, wheras cluster-md 10308c2ecf20Sopenharmony_ci * wants the number to be from zero, so we deduct one 10318c2ecf20Sopenharmony_ci */ 10328c2ecf20Sopenharmony_cistatic int slot_number(struct mddev *mddev) 10338c2ecf20Sopenharmony_ci{ 10348c2ecf20Sopenharmony_ci struct md_cluster_info *cinfo = mddev->cluster_info; 10358c2ecf20Sopenharmony_ci 10368c2ecf20Sopenharmony_ci return cinfo->slot_number - 1; 10378c2ecf20Sopenharmony_ci} 10388c2ecf20Sopenharmony_ci 10398c2ecf20Sopenharmony_ci/* 10408c2ecf20Sopenharmony_ci * Check if the communication is already locked, else lock the communication 10418c2ecf20Sopenharmony_ci * channel. 10428c2ecf20Sopenharmony_ci * If it is already locked, token is in EX mode, and hence lock_token() 10438c2ecf20Sopenharmony_ci * should not be called. 10448c2ecf20Sopenharmony_ci */ 10458c2ecf20Sopenharmony_cistatic int metadata_update_start(struct mddev *mddev) 10468c2ecf20Sopenharmony_ci{ 10478c2ecf20Sopenharmony_ci struct md_cluster_info *cinfo = mddev->cluster_info; 10488c2ecf20Sopenharmony_ci int ret; 10498c2ecf20Sopenharmony_ci 10508c2ecf20Sopenharmony_ci /* 10518c2ecf20Sopenharmony_ci * metadata_update_start is always called with the protection of 10528c2ecf20Sopenharmony_ci * reconfig_mutex, so set WAITING_FOR_TOKEN here. 10538c2ecf20Sopenharmony_ci */ 10548c2ecf20Sopenharmony_ci ret = test_and_set_bit_lock(MD_CLUSTER_HOLDING_MUTEX_FOR_RECVD, 10558c2ecf20Sopenharmony_ci &cinfo->state); 10568c2ecf20Sopenharmony_ci WARN_ON_ONCE(ret); 10578c2ecf20Sopenharmony_ci md_wakeup_thread(mddev->thread); 10588c2ecf20Sopenharmony_ci 10598c2ecf20Sopenharmony_ci wait_event(cinfo->wait, 10608c2ecf20Sopenharmony_ci !test_and_set_bit(MD_CLUSTER_SEND_LOCK, &cinfo->state) || 10618c2ecf20Sopenharmony_ci test_and_clear_bit(MD_CLUSTER_SEND_LOCKED_ALREADY, &cinfo->state)); 10628c2ecf20Sopenharmony_ci 10638c2ecf20Sopenharmony_ci /* If token is already locked, return 0 */ 10648c2ecf20Sopenharmony_ci if (cinfo->token_lockres->mode == DLM_LOCK_EX) { 10658c2ecf20Sopenharmony_ci clear_bit_unlock(MD_CLUSTER_HOLDING_MUTEX_FOR_RECVD, &cinfo->state); 10668c2ecf20Sopenharmony_ci return 0; 10678c2ecf20Sopenharmony_ci } 10688c2ecf20Sopenharmony_ci 10698c2ecf20Sopenharmony_ci ret = lock_token(cinfo); 10708c2ecf20Sopenharmony_ci clear_bit_unlock(MD_CLUSTER_HOLDING_MUTEX_FOR_RECVD, &cinfo->state); 10718c2ecf20Sopenharmony_ci return ret; 10728c2ecf20Sopenharmony_ci} 10738c2ecf20Sopenharmony_ci 10748c2ecf20Sopenharmony_cistatic int metadata_update_finish(struct mddev *mddev) 10758c2ecf20Sopenharmony_ci{ 10768c2ecf20Sopenharmony_ci struct md_cluster_info *cinfo = mddev->cluster_info; 10778c2ecf20Sopenharmony_ci struct cluster_msg cmsg; 10788c2ecf20Sopenharmony_ci struct md_rdev *rdev; 10798c2ecf20Sopenharmony_ci int ret = 0; 10808c2ecf20Sopenharmony_ci int raid_slot = -1; 10818c2ecf20Sopenharmony_ci 10828c2ecf20Sopenharmony_ci memset(&cmsg, 0, sizeof(cmsg)); 10838c2ecf20Sopenharmony_ci cmsg.type = cpu_to_le32(METADATA_UPDATED); 10848c2ecf20Sopenharmony_ci /* Pick up a good active device number to send. 10858c2ecf20Sopenharmony_ci */ 10868c2ecf20Sopenharmony_ci rdev_for_each(rdev, mddev) 10878c2ecf20Sopenharmony_ci if (rdev->raid_disk > -1 && !test_bit(Faulty, &rdev->flags)) { 10888c2ecf20Sopenharmony_ci raid_slot = rdev->desc_nr; 10898c2ecf20Sopenharmony_ci break; 10908c2ecf20Sopenharmony_ci } 10918c2ecf20Sopenharmony_ci if (raid_slot >= 0) { 10928c2ecf20Sopenharmony_ci cmsg.raid_slot = cpu_to_le32(raid_slot); 10938c2ecf20Sopenharmony_ci ret = __sendmsg(cinfo, &cmsg); 10948c2ecf20Sopenharmony_ci } else 10958c2ecf20Sopenharmony_ci pr_warn("md-cluster: No good device id found to send\n"); 10968c2ecf20Sopenharmony_ci clear_bit(MD_CLUSTER_SEND_LOCKED_ALREADY, &cinfo->state); 10978c2ecf20Sopenharmony_ci unlock_comm(cinfo); 10988c2ecf20Sopenharmony_ci return ret; 10998c2ecf20Sopenharmony_ci} 11008c2ecf20Sopenharmony_ci 11018c2ecf20Sopenharmony_cistatic void metadata_update_cancel(struct mddev *mddev) 11028c2ecf20Sopenharmony_ci{ 11038c2ecf20Sopenharmony_ci struct md_cluster_info *cinfo = mddev->cluster_info; 11048c2ecf20Sopenharmony_ci clear_bit(MD_CLUSTER_SEND_LOCKED_ALREADY, &cinfo->state); 11058c2ecf20Sopenharmony_ci unlock_comm(cinfo); 11068c2ecf20Sopenharmony_ci} 11078c2ecf20Sopenharmony_ci 11088c2ecf20Sopenharmony_cistatic int update_bitmap_size(struct mddev *mddev, sector_t size) 11098c2ecf20Sopenharmony_ci{ 11108c2ecf20Sopenharmony_ci struct md_cluster_info *cinfo = mddev->cluster_info; 11118c2ecf20Sopenharmony_ci struct cluster_msg cmsg = {0}; 11128c2ecf20Sopenharmony_ci int ret; 11138c2ecf20Sopenharmony_ci 11148c2ecf20Sopenharmony_ci cmsg.type = cpu_to_le32(BITMAP_RESIZE); 11158c2ecf20Sopenharmony_ci cmsg.high = cpu_to_le64(size); 11168c2ecf20Sopenharmony_ci ret = sendmsg(cinfo, &cmsg, 0); 11178c2ecf20Sopenharmony_ci if (ret) 11188c2ecf20Sopenharmony_ci pr_err("%s:%d: failed to send BITMAP_RESIZE message (%d)\n", 11198c2ecf20Sopenharmony_ci __func__, __LINE__, ret); 11208c2ecf20Sopenharmony_ci return ret; 11218c2ecf20Sopenharmony_ci} 11228c2ecf20Sopenharmony_ci 11238c2ecf20Sopenharmony_cistatic int resize_bitmaps(struct mddev *mddev, sector_t newsize, sector_t oldsize) 11248c2ecf20Sopenharmony_ci{ 11258c2ecf20Sopenharmony_ci struct bitmap_counts *counts; 11268c2ecf20Sopenharmony_ci char str[64]; 11278c2ecf20Sopenharmony_ci struct dlm_lock_resource *bm_lockres; 11288c2ecf20Sopenharmony_ci struct bitmap *bitmap = mddev->bitmap; 11298c2ecf20Sopenharmony_ci unsigned long my_pages = bitmap->counts.pages; 11308c2ecf20Sopenharmony_ci int i, rv; 11318c2ecf20Sopenharmony_ci 11328c2ecf20Sopenharmony_ci /* 11338c2ecf20Sopenharmony_ci * We need to ensure all the nodes can grow to a larger 11348c2ecf20Sopenharmony_ci * bitmap size before make the reshaping. 11358c2ecf20Sopenharmony_ci */ 11368c2ecf20Sopenharmony_ci rv = update_bitmap_size(mddev, newsize); 11378c2ecf20Sopenharmony_ci if (rv) 11388c2ecf20Sopenharmony_ci return rv; 11398c2ecf20Sopenharmony_ci 11408c2ecf20Sopenharmony_ci for (i = 0; i < mddev->bitmap_info.nodes; i++) { 11418c2ecf20Sopenharmony_ci if (i == md_cluster_ops->slot_number(mddev)) 11428c2ecf20Sopenharmony_ci continue; 11438c2ecf20Sopenharmony_ci 11448c2ecf20Sopenharmony_ci bitmap = get_bitmap_from_slot(mddev, i); 11458c2ecf20Sopenharmony_ci if (IS_ERR(bitmap)) { 11468c2ecf20Sopenharmony_ci pr_err("can't get bitmap from slot %d\n", i); 11478c2ecf20Sopenharmony_ci bitmap = NULL; 11488c2ecf20Sopenharmony_ci goto out; 11498c2ecf20Sopenharmony_ci } 11508c2ecf20Sopenharmony_ci counts = &bitmap->counts; 11518c2ecf20Sopenharmony_ci 11528c2ecf20Sopenharmony_ci /* 11538c2ecf20Sopenharmony_ci * If we can hold the bitmap lock of one node then 11548c2ecf20Sopenharmony_ci * the slot is not occupied, update the pages. 11558c2ecf20Sopenharmony_ci */ 11568c2ecf20Sopenharmony_ci snprintf(str, 64, "bitmap%04d", i); 11578c2ecf20Sopenharmony_ci bm_lockres = lockres_init(mddev, str, NULL, 1); 11588c2ecf20Sopenharmony_ci if (!bm_lockres) { 11598c2ecf20Sopenharmony_ci pr_err("Cannot initialize %s lock\n", str); 11608c2ecf20Sopenharmony_ci goto out; 11618c2ecf20Sopenharmony_ci } 11628c2ecf20Sopenharmony_ci bm_lockres->flags |= DLM_LKF_NOQUEUE; 11638c2ecf20Sopenharmony_ci rv = dlm_lock_sync(bm_lockres, DLM_LOCK_PW); 11648c2ecf20Sopenharmony_ci if (!rv) 11658c2ecf20Sopenharmony_ci counts->pages = my_pages; 11668c2ecf20Sopenharmony_ci lockres_free(bm_lockres); 11678c2ecf20Sopenharmony_ci 11688c2ecf20Sopenharmony_ci if (my_pages != counts->pages) 11698c2ecf20Sopenharmony_ci /* 11708c2ecf20Sopenharmony_ci * Let's revert the bitmap size if one node 11718c2ecf20Sopenharmony_ci * can't resize bitmap 11728c2ecf20Sopenharmony_ci */ 11738c2ecf20Sopenharmony_ci goto out; 11748c2ecf20Sopenharmony_ci md_bitmap_free(bitmap); 11758c2ecf20Sopenharmony_ci } 11768c2ecf20Sopenharmony_ci 11778c2ecf20Sopenharmony_ci return 0; 11788c2ecf20Sopenharmony_ciout: 11798c2ecf20Sopenharmony_ci md_bitmap_free(bitmap); 11808c2ecf20Sopenharmony_ci update_bitmap_size(mddev, oldsize); 11818c2ecf20Sopenharmony_ci return -1; 11828c2ecf20Sopenharmony_ci} 11838c2ecf20Sopenharmony_ci 11848c2ecf20Sopenharmony_ci/* 11858c2ecf20Sopenharmony_ci * return 0 if all the bitmaps have the same sync_size 11868c2ecf20Sopenharmony_ci */ 11878c2ecf20Sopenharmony_cistatic int cluster_check_sync_size(struct mddev *mddev) 11888c2ecf20Sopenharmony_ci{ 11898c2ecf20Sopenharmony_ci int i, rv; 11908c2ecf20Sopenharmony_ci bitmap_super_t *sb; 11918c2ecf20Sopenharmony_ci unsigned long my_sync_size, sync_size = 0; 11928c2ecf20Sopenharmony_ci int node_num = mddev->bitmap_info.nodes; 11938c2ecf20Sopenharmony_ci int current_slot = md_cluster_ops->slot_number(mddev); 11948c2ecf20Sopenharmony_ci struct bitmap *bitmap = mddev->bitmap; 11958c2ecf20Sopenharmony_ci char str[64]; 11968c2ecf20Sopenharmony_ci struct dlm_lock_resource *bm_lockres; 11978c2ecf20Sopenharmony_ci 11988c2ecf20Sopenharmony_ci sb = kmap_atomic(bitmap->storage.sb_page); 11998c2ecf20Sopenharmony_ci my_sync_size = sb->sync_size; 12008c2ecf20Sopenharmony_ci kunmap_atomic(sb); 12018c2ecf20Sopenharmony_ci 12028c2ecf20Sopenharmony_ci for (i = 0; i < node_num; i++) { 12038c2ecf20Sopenharmony_ci if (i == current_slot) 12048c2ecf20Sopenharmony_ci continue; 12058c2ecf20Sopenharmony_ci 12068c2ecf20Sopenharmony_ci bitmap = get_bitmap_from_slot(mddev, i); 12078c2ecf20Sopenharmony_ci if (IS_ERR(bitmap)) { 12088c2ecf20Sopenharmony_ci pr_err("can't get bitmap from slot %d\n", i); 12098c2ecf20Sopenharmony_ci return -1; 12108c2ecf20Sopenharmony_ci } 12118c2ecf20Sopenharmony_ci 12128c2ecf20Sopenharmony_ci /* 12138c2ecf20Sopenharmony_ci * If we can hold the bitmap lock of one node then 12148c2ecf20Sopenharmony_ci * the slot is not occupied, update the sb. 12158c2ecf20Sopenharmony_ci */ 12168c2ecf20Sopenharmony_ci snprintf(str, 64, "bitmap%04d", i); 12178c2ecf20Sopenharmony_ci bm_lockres = lockres_init(mddev, str, NULL, 1); 12188c2ecf20Sopenharmony_ci if (!bm_lockres) { 12198c2ecf20Sopenharmony_ci pr_err("md-cluster: Cannot initialize %s\n", str); 12208c2ecf20Sopenharmony_ci md_bitmap_free(bitmap); 12218c2ecf20Sopenharmony_ci return -1; 12228c2ecf20Sopenharmony_ci } 12238c2ecf20Sopenharmony_ci bm_lockres->flags |= DLM_LKF_NOQUEUE; 12248c2ecf20Sopenharmony_ci rv = dlm_lock_sync(bm_lockres, DLM_LOCK_PW); 12258c2ecf20Sopenharmony_ci if (!rv) 12268c2ecf20Sopenharmony_ci md_bitmap_update_sb(bitmap); 12278c2ecf20Sopenharmony_ci lockres_free(bm_lockres); 12288c2ecf20Sopenharmony_ci 12298c2ecf20Sopenharmony_ci sb = kmap_atomic(bitmap->storage.sb_page); 12308c2ecf20Sopenharmony_ci if (sync_size == 0) 12318c2ecf20Sopenharmony_ci sync_size = sb->sync_size; 12328c2ecf20Sopenharmony_ci else if (sync_size != sb->sync_size) { 12338c2ecf20Sopenharmony_ci kunmap_atomic(sb); 12348c2ecf20Sopenharmony_ci md_bitmap_free(bitmap); 12358c2ecf20Sopenharmony_ci return -1; 12368c2ecf20Sopenharmony_ci } 12378c2ecf20Sopenharmony_ci kunmap_atomic(sb); 12388c2ecf20Sopenharmony_ci md_bitmap_free(bitmap); 12398c2ecf20Sopenharmony_ci } 12408c2ecf20Sopenharmony_ci 12418c2ecf20Sopenharmony_ci return (my_sync_size == sync_size) ? 0 : -1; 12428c2ecf20Sopenharmony_ci} 12438c2ecf20Sopenharmony_ci 12448c2ecf20Sopenharmony_ci/* 12458c2ecf20Sopenharmony_ci * Update the size for cluster raid is a little more complex, we perform it 12468c2ecf20Sopenharmony_ci * by the steps: 12478c2ecf20Sopenharmony_ci * 1. hold token lock and update superblock in initiator node. 12488c2ecf20Sopenharmony_ci * 2. send METADATA_UPDATED msg to other nodes. 12498c2ecf20Sopenharmony_ci * 3. The initiator node continues to check each bitmap's sync_size, if all 12508c2ecf20Sopenharmony_ci * bitmaps have the same value of sync_size, then we can set capacity and 12518c2ecf20Sopenharmony_ci * let other nodes to perform it. If one node can't update sync_size 12528c2ecf20Sopenharmony_ci * accordingly, we need to revert to previous value. 12538c2ecf20Sopenharmony_ci */ 12548c2ecf20Sopenharmony_cistatic void update_size(struct mddev *mddev, sector_t old_dev_sectors) 12558c2ecf20Sopenharmony_ci{ 12568c2ecf20Sopenharmony_ci struct md_cluster_info *cinfo = mddev->cluster_info; 12578c2ecf20Sopenharmony_ci struct cluster_msg cmsg; 12588c2ecf20Sopenharmony_ci struct md_rdev *rdev; 12598c2ecf20Sopenharmony_ci int ret = 0; 12608c2ecf20Sopenharmony_ci int raid_slot = -1; 12618c2ecf20Sopenharmony_ci 12628c2ecf20Sopenharmony_ci md_update_sb(mddev, 1); 12638c2ecf20Sopenharmony_ci if (lock_comm(cinfo, 1)) { 12648c2ecf20Sopenharmony_ci pr_err("%s: lock_comm failed\n", __func__); 12658c2ecf20Sopenharmony_ci return; 12668c2ecf20Sopenharmony_ci } 12678c2ecf20Sopenharmony_ci 12688c2ecf20Sopenharmony_ci memset(&cmsg, 0, sizeof(cmsg)); 12698c2ecf20Sopenharmony_ci cmsg.type = cpu_to_le32(METADATA_UPDATED); 12708c2ecf20Sopenharmony_ci rdev_for_each(rdev, mddev) 12718c2ecf20Sopenharmony_ci if (rdev->raid_disk >= 0 && !test_bit(Faulty, &rdev->flags)) { 12728c2ecf20Sopenharmony_ci raid_slot = rdev->desc_nr; 12738c2ecf20Sopenharmony_ci break; 12748c2ecf20Sopenharmony_ci } 12758c2ecf20Sopenharmony_ci if (raid_slot >= 0) { 12768c2ecf20Sopenharmony_ci cmsg.raid_slot = cpu_to_le32(raid_slot); 12778c2ecf20Sopenharmony_ci /* 12788c2ecf20Sopenharmony_ci * We can only change capiticy after all the nodes can do it, 12798c2ecf20Sopenharmony_ci * so need to wait after other nodes already received the msg 12808c2ecf20Sopenharmony_ci * and handled the change 12818c2ecf20Sopenharmony_ci */ 12828c2ecf20Sopenharmony_ci ret = __sendmsg(cinfo, &cmsg); 12838c2ecf20Sopenharmony_ci if (ret) { 12848c2ecf20Sopenharmony_ci pr_err("%s:%d: failed to send METADATA_UPDATED msg\n", 12858c2ecf20Sopenharmony_ci __func__, __LINE__); 12868c2ecf20Sopenharmony_ci unlock_comm(cinfo); 12878c2ecf20Sopenharmony_ci return; 12888c2ecf20Sopenharmony_ci } 12898c2ecf20Sopenharmony_ci } else { 12908c2ecf20Sopenharmony_ci pr_err("md-cluster: No good device id found to send\n"); 12918c2ecf20Sopenharmony_ci unlock_comm(cinfo); 12928c2ecf20Sopenharmony_ci return; 12938c2ecf20Sopenharmony_ci } 12948c2ecf20Sopenharmony_ci 12958c2ecf20Sopenharmony_ci /* 12968c2ecf20Sopenharmony_ci * check the sync_size from other node's bitmap, if sync_size 12978c2ecf20Sopenharmony_ci * have already updated in other nodes as expected, send an 12988c2ecf20Sopenharmony_ci * empty metadata msg to permit the change of capacity 12998c2ecf20Sopenharmony_ci */ 13008c2ecf20Sopenharmony_ci if (cluster_check_sync_size(mddev) == 0) { 13018c2ecf20Sopenharmony_ci memset(&cmsg, 0, sizeof(cmsg)); 13028c2ecf20Sopenharmony_ci cmsg.type = cpu_to_le32(CHANGE_CAPACITY); 13038c2ecf20Sopenharmony_ci ret = __sendmsg(cinfo, &cmsg); 13048c2ecf20Sopenharmony_ci if (ret) 13058c2ecf20Sopenharmony_ci pr_err("%s:%d: failed to send CHANGE_CAPACITY msg\n", 13068c2ecf20Sopenharmony_ci __func__, __LINE__); 13078c2ecf20Sopenharmony_ci set_capacity(mddev->gendisk, mddev->array_sectors); 13088c2ecf20Sopenharmony_ci revalidate_disk_size(mddev->gendisk, true); 13098c2ecf20Sopenharmony_ci } else { 13108c2ecf20Sopenharmony_ci /* revert to previous sectors */ 13118c2ecf20Sopenharmony_ci ret = mddev->pers->resize(mddev, old_dev_sectors); 13128c2ecf20Sopenharmony_ci if (!ret) 13138c2ecf20Sopenharmony_ci revalidate_disk_size(mddev->gendisk, true); 13148c2ecf20Sopenharmony_ci ret = __sendmsg(cinfo, &cmsg); 13158c2ecf20Sopenharmony_ci if (ret) 13168c2ecf20Sopenharmony_ci pr_err("%s:%d: failed to send METADATA_UPDATED msg\n", 13178c2ecf20Sopenharmony_ci __func__, __LINE__); 13188c2ecf20Sopenharmony_ci } 13198c2ecf20Sopenharmony_ci unlock_comm(cinfo); 13208c2ecf20Sopenharmony_ci} 13218c2ecf20Sopenharmony_ci 13228c2ecf20Sopenharmony_cistatic int resync_start(struct mddev *mddev) 13238c2ecf20Sopenharmony_ci{ 13248c2ecf20Sopenharmony_ci struct md_cluster_info *cinfo = mddev->cluster_info; 13258c2ecf20Sopenharmony_ci return dlm_lock_sync_interruptible(cinfo->resync_lockres, DLM_LOCK_EX, mddev); 13268c2ecf20Sopenharmony_ci} 13278c2ecf20Sopenharmony_ci 13288c2ecf20Sopenharmony_cistatic void resync_info_get(struct mddev *mddev, sector_t *lo, sector_t *hi) 13298c2ecf20Sopenharmony_ci{ 13308c2ecf20Sopenharmony_ci struct md_cluster_info *cinfo = mddev->cluster_info; 13318c2ecf20Sopenharmony_ci 13328c2ecf20Sopenharmony_ci spin_lock_irq(&cinfo->suspend_lock); 13338c2ecf20Sopenharmony_ci *lo = cinfo->suspend_lo; 13348c2ecf20Sopenharmony_ci *hi = cinfo->suspend_hi; 13358c2ecf20Sopenharmony_ci spin_unlock_irq(&cinfo->suspend_lock); 13368c2ecf20Sopenharmony_ci} 13378c2ecf20Sopenharmony_ci 13388c2ecf20Sopenharmony_cistatic int resync_info_update(struct mddev *mddev, sector_t lo, sector_t hi) 13398c2ecf20Sopenharmony_ci{ 13408c2ecf20Sopenharmony_ci struct md_cluster_info *cinfo = mddev->cluster_info; 13418c2ecf20Sopenharmony_ci struct resync_info ri; 13428c2ecf20Sopenharmony_ci struct cluster_msg cmsg = {0}; 13438c2ecf20Sopenharmony_ci 13448c2ecf20Sopenharmony_ci /* do not send zero again, if we have sent before */ 13458c2ecf20Sopenharmony_ci if (hi == 0) { 13468c2ecf20Sopenharmony_ci memcpy(&ri, cinfo->bitmap_lockres->lksb.sb_lvbptr, sizeof(struct resync_info)); 13478c2ecf20Sopenharmony_ci if (le64_to_cpu(ri.hi) == 0) 13488c2ecf20Sopenharmony_ci return 0; 13498c2ecf20Sopenharmony_ci } 13508c2ecf20Sopenharmony_ci 13518c2ecf20Sopenharmony_ci add_resync_info(cinfo->bitmap_lockres, lo, hi); 13528c2ecf20Sopenharmony_ci /* Re-acquire the lock to refresh LVB */ 13538c2ecf20Sopenharmony_ci dlm_lock_sync(cinfo->bitmap_lockres, DLM_LOCK_PW); 13548c2ecf20Sopenharmony_ci cmsg.type = cpu_to_le32(RESYNCING); 13558c2ecf20Sopenharmony_ci cmsg.low = cpu_to_le64(lo); 13568c2ecf20Sopenharmony_ci cmsg.high = cpu_to_le64(hi); 13578c2ecf20Sopenharmony_ci 13588c2ecf20Sopenharmony_ci /* 13598c2ecf20Sopenharmony_ci * mddev_lock is held if resync_info_update is called from 13608c2ecf20Sopenharmony_ci * resync_finish (md_reap_sync_thread -> resync_finish) 13618c2ecf20Sopenharmony_ci */ 13628c2ecf20Sopenharmony_ci if (lo == 0 && hi == 0) 13638c2ecf20Sopenharmony_ci return sendmsg(cinfo, &cmsg, 1); 13648c2ecf20Sopenharmony_ci else 13658c2ecf20Sopenharmony_ci return sendmsg(cinfo, &cmsg, 0); 13668c2ecf20Sopenharmony_ci} 13678c2ecf20Sopenharmony_ci 13688c2ecf20Sopenharmony_cistatic int resync_finish(struct mddev *mddev) 13698c2ecf20Sopenharmony_ci{ 13708c2ecf20Sopenharmony_ci struct md_cluster_info *cinfo = mddev->cluster_info; 13718c2ecf20Sopenharmony_ci int ret = 0; 13728c2ecf20Sopenharmony_ci 13738c2ecf20Sopenharmony_ci clear_bit(MD_RESYNCING_REMOTE, &mddev->recovery); 13748c2ecf20Sopenharmony_ci 13758c2ecf20Sopenharmony_ci /* 13768c2ecf20Sopenharmony_ci * If resync thread is interrupted so we can't say resync is finished, 13778c2ecf20Sopenharmony_ci * another node will launch resync thread to continue. 13788c2ecf20Sopenharmony_ci */ 13798c2ecf20Sopenharmony_ci if (!test_bit(MD_CLOSING, &mddev->flags)) 13808c2ecf20Sopenharmony_ci ret = resync_info_update(mddev, 0, 0); 13818c2ecf20Sopenharmony_ci dlm_unlock_sync(cinfo->resync_lockres); 13828c2ecf20Sopenharmony_ci return ret; 13838c2ecf20Sopenharmony_ci} 13848c2ecf20Sopenharmony_ci 13858c2ecf20Sopenharmony_cistatic int area_resyncing(struct mddev *mddev, int direction, 13868c2ecf20Sopenharmony_ci sector_t lo, sector_t hi) 13878c2ecf20Sopenharmony_ci{ 13888c2ecf20Sopenharmony_ci struct md_cluster_info *cinfo = mddev->cluster_info; 13898c2ecf20Sopenharmony_ci int ret = 0; 13908c2ecf20Sopenharmony_ci 13918c2ecf20Sopenharmony_ci if ((direction == READ) && 13928c2ecf20Sopenharmony_ci test_bit(MD_CLUSTER_SUSPEND_READ_BALANCING, &cinfo->state)) 13938c2ecf20Sopenharmony_ci return 1; 13948c2ecf20Sopenharmony_ci 13958c2ecf20Sopenharmony_ci spin_lock_irq(&cinfo->suspend_lock); 13968c2ecf20Sopenharmony_ci if (hi > cinfo->suspend_lo && lo < cinfo->suspend_hi) 13978c2ecf20Sopenharmony_ci ret = 1; 13988c2ecf20Sopenharmony_ci spin_unlock_irq(&cinfo->suspend_lock); 13998c2ecf20Sopenharmony_ci return ret; 14008c2ecf20Sopenharmony_ci} 14018c2ecf20Sopenharmony_ci 14028c2ecf20Sopenharmony_ci/* add_new_disk() - initiates a disk add 14038c2ecf20Sopenharmony_ci * However, if this fails before writing md_update_sb(), 14048c2ecf20Sopenharmony_ci * add_new_disk_cancel() must be called to release token lock 14058c2ecf20Sopenharmony_ci */ 14068c2ecf20Sopenharmony_cistatic int add_new_disk(struct mddev *mddev, struct md_rdev *rdev) 14078c2ecf20Sopenharmony_ci{ 14088c2ecf20Sopenharmony_ci struct md_cluster_info *cinfo = mddev->cluster_info; 14098c2ecf20Sopenharmony_ci struct cluster_msg cmsg; 14108c2ecf20Sopenharmony_ci int ret = 0; 14118c2ecf20Sopenharmony_ci struct mdp_superblock_1 *sb = page_address(rdev->sb_page); 14128c2ecf20Sopenharmony_ci char *uuid = sb->device_uuid; 14138c2ecf20Sopenharmony_ci 14148c2ecf20Sopenharmony_ci memset(&cmsg, 0, sizeof(cmsg)); 14158c2ecf20Sopenharmony_ci cmsg.type = cpu_to_le32(NEWDISK); 14168c2ecf20Sopenharmony_ci memcpy(cmsg.uuid, uuid, 16); 14178c2ecf20Sopenharmony_ci cmsg.raid_slot = cpu_to_le32(rdev->desc_nr); 14188c2ecf20Sopenharmony_ci if (lock_comm(cinfo, 1)) 14198c2ecf20Sopenharmony_ci return -EAGAIN; 14208c2ecf20Sopenharmony_ci ret = __sendmsg(cinfo, &cmsg); 14218c2ecf20Sopenharmony_ci if (ret) { 14228c2ecf20Sopenharmony_ci unlock_comm(cinfo); 14238c2ecf20Sopenharmony_ci return ret; 14248c2ecf20Sopenharmony_ci } 14258c2ecf20Sopenharmony_ci cinfo->no_new_dev_lockres->flags |= DLM_LKF_NOQUEUE; 14268c2ecf20Sopenharmony_ci ret = dlm_lock_sync(cinfo->no_new_dev_lockres, DLM_LOCK_EX); 14278c2ecf20Sopenharmony_ci cinfo->no_new_dev_lockres->flags &= ~DLM_LKF_NOQUEUE; 14288c2ecf20Sopenharmony_ci /* Some node does not "see" the device */ 14298c2ecf20Sopenharmony_ci if (ret == -EAGAIN) 14308c2ecf20Sopenharmony_ci ret = -ENOENT; 14318c2ecf20Sopenharmony_ci if (ret) 14328c2ecf20Sopenharmony_ci unlock_comm(cinfo); 14338c2ecf20Sopenharmony_ci else { 14348c2ecf20Sopenharmony_ci dlm_lock_sync(cinfo->no_new_dev_lockres, DLM_LOCK_CR); 14358c2ecf20Sopenharmony_ci /* Since MD_CHANGE_DEVS will be set in add_bound_rdev which 14368c2ecf20Sopenharmony_ci * will run soon after add_new_disk, the below path will be 14378c2ecf20Sopenharmony_ci * invoked: 14388c2ecf20Sopenharmony_ci * md_wakeup_thread(mddev->thread) 14398c2ecf20Sopenharmony_ci * -> conf->thread (raid1d) 14408c2ecf20Sopenharmony_ci * -> md_check_recovery -> md_update_sb 14418c2ecf20Sopenharmony_ci * -> metadata_update_start/finish 14428c2ecf20Sopenharmony_ci * MD_CLUSTER_SEND_LOCKED_ALREADY will be cleared eventually. 14438c2ecf20Sopenharmony_ci * 14448c2ecf20Sopenharmony_ci * For other failure cases, metadata_update_cancel and 14458c2ecf20Sopenharmony_ci * add_new_disk_cancel also clear below bit as well. 14468c2ecf20Sopenharmony_ci * */ 14478c2ecf20Sopenharmony_ci set_bit(MD_CLUSTER_SEND_LOCKED_ALREADY, &cinfo->state); 14488c2ecf20Sopenharmony_ci wake_up(&cinfo->wait); 14498c2ecf20Sopenharmony_ci } 14508c2ecf20Sopenharmony_ci return ret; 14518c2ecf20Sopenharmony_ci} 14528c2ecf20Sopenharmony_ci 14538c2ecf20Sopenharmony_cistatic void add_new_disk_cancel(struct mddev *mddev) 14548c2ecf20Sopenharmony_ci{ 14558c2ecf20Sopenharmony_ci struct md_cluster_info *cinfo = mddev->cluster_info; 14568c2ecf20Sopenharmony_ci clear_bit(MD_CLUSTER_SEND_LOCKED_ALREADY, &cinfo->state); 14578c2ecf20Sopenharmony_ci unlock_comm(cinfo); 14588c2ecf20Sopenharmony_ci} 14598c2ecf20Sopenharmony_ci 14608c2ecf20Sopenharmony_cistatic int new_disk_ack(struct mddev *mddev, bool ack) 14618c2ecf20Sopenharmony_ci{ 14628c2ecf20Sopenharmony_ci struct md_cluster_info *cinfo = mddev->cluster_info; 14638c2ecf20Sopenharmony_ci 14648c2ecf20Sopenharmony_ci if (!test_bit(MD_CLUSTER_WAITING_FOR_NEWDISK, &cinfo->state)) { 14658c2ecf20Sopenharmony_ci pr_warn("md-cluster(%s): Spurious cluster confirmation\n", mdname(mddev)); 14668c2ecf20Sopenharmony_ci return -EINVAL; 14678c2ecf20Sopenharmony_ci } 14688c2ecf20Sopenharmony_ci 14698c2ecf20Sopenharmony_ci if (ack) 14708c2ecf20Sopenharmony_ci dlm_unlock_sync(cinfo->no_new_dev_lockres); 14718c2ecf20Sopenharmony_ci complete(&cinfo->newdisk_completion); 14728c2ecf20Sopenharmony_ci return 0; 14738c2ecf20Sopenharmony_ci} 14748c2ecf20Sopenharmony_ci 14758c2ecf20Sopenharmony_cistatic int remove_disk(struct mddev *mddev, struct md_rdev *rdev) 14768c2ecf20Sopenharmony_ci{ 14778c2ecf20Sopenharmony_ci struct cluster_msg cmsg = {0}; 14788c2ecf20Sopenharmony_ci struct md_cluster_info *cinfo = mddev->cluster_info; 14798c2ecf20Sopenharmony_ci cmsg.type = cpu_to_le32(REMOVE); 14808c2ecf20Sopenharmony_ci cmsg.raid_slot = cpu_to_le32(rdev->desc_nr); 14818c2ecf20Sopenharmony_ci return sendmsg(cinfo, &cmsg, 1); 14828c2ecf20Sopenharmony_ci} 14838c2ecf20Sopenharmony_ci 14848c2ecf20Sopenharmony_cistatic int lock_all_bitmaps(struct mddev *mddev) 14858c2ecf20Sopenharmony_ci{ 14868c2ecf20Sopenharmony_ci int slot, my_slot, ret, held = 1, i = 0; 14878c2ecf20Sopenharmony_ci char str[64]; 14888c2ecf20Sopenharmony_ci struct md_cluster_info *cinfo = mddev->cluster_info; 14898c2ecf20Sopenharmony_ci 14908c2ecf20Sopenharmony_ci cinfo->other_bitmap_lockres = 14918c2ecf20Sopenharmony_ci kcalloc(mddev->bitmap_info.nodes - 1, 14928c2ecf20Sopenharmony_ci sizeof(struct dlm_lock_resource *), GFP_KERNEL); 14938c2ecf20Sopenharmony_ci if (!cinfo->other_bitmap_lockres) { 14948c2ecf20Sopenharmony_ci pr_err("md: can't alloc mem for other bitmap locks\n"); 14958c2ecf20Sopenharmony_ci return 0; 14968c2ecf20Sopenharmony_ci } 14978c2ecf20Sopenharmony_ci 14988c2ecf20Sopenharmony_ci my_slot = slot_number(mddev); 14998c2ecf20Sopenharmony_ci for (slot = 0; slot < mddev->bitmap_info.nodes; slot++) { 15008c2ecf20Sopenharmony_ci if (slot == my_slot) 15018c2ecf20Sopenharmony_ci continue; 15028c2ecf20Sopenharmony_ci 15038c2ecf20Sopenharmony_ci memset(str, '\0', 64); 15048c2ecf20Sopenharmony_ci snprintf(str, 64, "bitmap%04d", slot); 15058c2ecf20Sopenharmony_ci cinfo->other_bitmap_lockres[i] = lockres_init(mddev, str, NULL, 1); 15068c2ecf20Sopenharmony_ci if (!cinfo->other_bitmap_lockres[i]) 15078c2ecf20Sopenharmony_ci return -ENOMEM; 15088c2ecf20Sopenharmony_ci 15098c2ecf20Sopenharmony_ci cinfo->other_bitmap_lockres[i]->flags |= DLM_LKF_NOQUEUE; 15108c2ecf20Sopenharmony_ci ret = dlm_lock_sync(cinfo->other_bitmap_lockres[i], DLM_LOCK_PW); 15118c2ecf20Sopenharmony_ci if (ret) 15128c2ecf20Sopenharmony_ci held = -1; 15138c2ecf20Sopenharmony_ci i++; 15148c2ecf20Sopenharmony_ci } 15158c2ecf20Sopenharmony_ci 15168c2ecf20Sopenharmony_ci return held; 15178c2ecf20Sopenharmony_ci} 15188c2ecf20Sopenharmony_ci 15198c2ecf20Sopenharmony_cistatic void unlock_all_bitmaps(struct mddev *mddev) 15208c2ecf20Sopenharmony_ci{ 15218c2ecf20Sopenharmony_ci struct md_cluster_info *cinfo = mddev->cluster_info; 15228c2ecf20Sopenharmony_ci int i; 15238c2ecf20Sopenharmony_ci 15248c2ecf20Sopenharmony_ci /* release other node's bitmap lock if they are existed */ 15258c2ecf20Sopenharmony_ci if (cinfo->other_bitmap_lockres) { 15268c2ecf20Sopenharmony_ci for (i = 0; i < mddev->bitmap_info.nodes - 1; i++) { 15278c2ecf20Sopenharmony_ci if (cinfo->other_bitmap_lockres[i]) { 15288c2ecf20Sopenharmony_ci lockres_free(cinfo->other_bitmap_lockres[i]); 15298c2ecf20Sopenharmony_ci } 15308c2ecf20Sopenharmony_ci } 15318c2ecf20Sopenharmony_ci kfree(cinfo->other_bitmap_lockres); 15328c2ecf20Sopenharmony_ci cinfo->other_bitmap_lockres = NULL; 15338c2ecf20Sopenharmony_ci } 15348c2ecf20Sopenharmony_ci} 15358c2ecf20Sopenharmony_ci 15368c2ecf20Sopenharmony_cistatic int gather_bitmaps(struct md_rdev *rdev) 15378c2ecf20Sopenharmony_ci{ 15388c2ecf20Sopenharmony_ci int sn, err; 15398c2ecf20Sopenharmony_ci sector_t lo, hi; 15408c2ecf20Sopenharmony_ci struct cluster_msg cmsg = {0}; 15418c2ecf20Sopenharmony_ci struct mddev *mddev = rdev->mddev; 15428c2ecf20Sopenharmony_ci struct md_cluster_info *cinfo = mddev->cluster_info; 15438c2ecf20Sopenharmony_ci 15448c2ecf20Sopenharmony_ci cmsg.type = cpu_to_le32(RE_ADD); 15458c2ecf20Sopenharmony_ci cmsg.raid_slot = cpu_to_le32(rdev->desc_nr); 15468c2ecf20Sopenharmony_ci err = sendmsg(cinfo, &cmsg, 1); 15478c2ecf20Sopenharmony_ci if (err) 15488c2ecf20Sopenharmony_ci goto out; 15498c2ecf20Sopenharmony_ci 15508c2ecf20Sopenharmony_ci for (sn = 0; sn < mddev->bitmap_info.nodes; sn++) { 15518c2ecf20Sopenharmony_ci if (sn == (cinfo->slot_number - 1)) 15528c2ecf20Sopenharmony_ci continue; 15538c2ecf20Sopenharmony_ci err = md_bitmap_copy_from_slot(mddev, sn, &lo, &hi, false); 15548c2ecf20Sopenharmony_ci if (err) { 15558c2ecf20Sopenharmony_ci pr_warn("md-cluster: Could not gather bitmaps from slot %d", sn); 15568c2ecf20Sopenharmony_ci goto out; 15578c2ecf20Sopenharmony_ci } 15588c2ecf20Sopenharmony_ci if ((hi > 0) && (lo < mddev->recovery_cp)) 15598c2ecf20Sopenharmony_ci mddev->recovery_cp = lo; 15608c2ecf20Sopenharmony_ci } 15618c2ecf20Sopenharmony_ciout: 15628c2ecf20Sopenharmony_ci return err; 15638c2ecf20Sopenharmony_ci} 15648c2ecf20Sopenharmony_ci 15658c2ecf20Sopenharmony_cistatic struct md_cluster_operations cluster_ops = { 15668c2ecf20Sopenharmony_ci .join = join, 15678c2ecf20Sopenharmony_ci .leave = leave, 15688c2ecf20Sopenharmony_ci .slot_number = slot_number, 15698c2ecf20Sopenharmony_ci .resync_start = resync_start, 15708c2ecf20Sopenharmony_ci .resync_finish = resync_finish, 15718c2ecf20Sopenharmony_ci .resync_info_update = resync_info_update, 15728c2ecf20Sopenharmony_ci .resync_info_get = resync_info_get, 15738c2ecf20Sopenharmony_ci .metadata_update_start = metadata_update_start, 15748c2ecf20Sopenharmony_ci .metadata_update_finish = metadata_update_finish, 15758c2ecf20Sopenharmony_ci .metadata_update_cancel = metadata_update_cancel, 15768c2ecf20Sopenharmony_ci .area_resyncing = area_resyncing, 15778c2ecf20Sopenharmony_ci .add_new_disk = add_new_disk, 15788c2ecf20Sopenharmony_ci .add_new_disk_cancel = add_new_disk_cancel, 15798c2ecf20Sopenharmony_ci .new_disk_ack = new_disk_ack, 15808c2ecf20Sopenharmony_ci .remove_disk = remove_disk, 15818c2ecf20Sopenharmony_ci .load_bitmaps = load_bitmaps, 15828c2ecf20Sopenharmony_ci .gather_bitmaps = gather_bitmaps, 15838c2ecf20Sopenharmony_ci .resize_bitmaps = resize_bitmaps, 15848c2ecf20Sopenharmony_ci .lock_all_bitmaps = lock_all_bitmaps, 15858c2ecf20Sopenharmony_ci .unlock_all_bitmaps = unlock_all_bitmaps, 15868c2ecf20Sopenharmony_ci .update_size = update_size, 15878c2ecf20Sopenharmony_ci}; 15888c2ecf20Sopenharmony_ci 15898c2ecf20Sopenharmony_cistatic int __init cluster_init(void) 15908c2ecf20Sopenharmony_ci{ 15918c2ecf20Sopenharmony_ci pr_warn("md-cluster: support raid1 and raid10 (limited support)\n"); 15928c2ecf20Sopenharmony_ci pr_info("Registering Cluster MD functions\n"); 15938c2ecf20Sopenharmony_ci register_md_cluster_operations(&cluster_ops, THIS_MODULE); 15948c2ecf20Sopenharmony_ci return 0; 15958c2ecf20Sopenharmony_ci} 15968c2ecf20Sopenharmony_ci 15978c2ecf20Sopenharmony_cistatic void cluster_exit(void) 15988c2ecf20Sopenharmony_ci{ 15998c2ecf20Sopenharmony_ci unregister_md_cluster_operations(); 16008c2ecf20Sopenharmony_ci} 16018c2ecf20Sopenharmony_ci 16028c2ecf20Sopenharmony_cimodule_init(cluster_init); 16038c2ecf20Sopenharmony_cimodule_exit(cluster_exit); 16048c2ecf20Sopenharmony_ciMODULE_AUTHOR("SUSE"); 16058c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL"); 16068c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("Clustering support for MD"); 1607