18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 28c2ecf20Sopenharmony_ci/* -*- mode: c; c-basic-offset: 8; -*- 38c2ecf20Sopenharmony_ci * vim: noexpandtab sw=8 ts=8 sts=0: 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * stack_o2cb.c 68c2ecf20Sopenharmony_ci * 78c2ecf20Sopenharmony_ci * Code which interfaces ocfs2 with the o2cb stack. 88c2ecf20Sopenharmony_ci * 98c2ecf20Sopenharmony_ci * Copyright (C) 2007 Oracle. All rights reserved. 108c2ecf20Sopenharmony_ci */ 118c2ecf20Sopenharmony_ci 128c2ecf20Sopenharmony_ci#include <linux/kernel.h> 138c2ecf20Sopenharmony_ci#include <linux/crc32.h> 148c2ecf20Sopenharmony_ci#include <linux/slab.h> 158c2ecf20Sopenharmony_ci#include <linux/module.h> 168c2ecf20Sopenharmony_ci 178c2ecf20Sopenharmony_ci/* Needed for AOP_TRUNCATED_PAGE in mlog_errno() */ 188c2ecf20Sopenharmony_ci#include <linux/fs.h> 198c2ecf20Sopenharmony_ci 208c2ecf20Sopenharmony_ci#include "cluster/masklog.h" 218c2ecf20Sopenharmony_ci#include "cluster/nodemanager.h" 228c2ecf20Sopenharmony_ci#include "cluster/heartbeat.h" 238c2ecf20Sopenharmony_ci#include "cluster/tcp.h" 248c2ecf20Sopenharmony_ci 258c2ecf20Sopenharmony_ci#include "stackglue.h" 268c2ecf20Sopenharmony_ci 278c2ecf20Sopenharmony_cistruct o2dlm_private { 288c2ecf20Sopenharmony_ci struct dlm_eviction_cb op_eviction_cb; 298c2ecf20Sopenharmony_ci}; 308c2ecf20Sopenharmony_ci 318c2ecf20Sopenharmony_cistatic struct ocfs2_stack_plugin o2cb_stack; 328c2ecf20Sopenharmony_ci 338c2ecf20Sopenharmony_ci/* These should be identical */ 348c2ecf20Sopenharmony_ci#if (DLM_LOCK_IV != LKM_IVMODE) 358c2ecf20Sopenharmony_ci# error Lock modes do not match 368c2ecf20Sopenharmony_ci#endif 378c2ecf20Sopenharmony_ci#if (DLM_LOCK_NL != LKM_NLMODE) 388c2ecf20Sopenharmony_ci# error Lock modes do not match 398c2ecf20Sopenharmony_ci#endif 408c2ecf20Sopenharmony_ci#if (DLM_LOCK_CR != LKM_CRMODE) 418c2ecf20Sopenharmony_ci# error Lock modes do not match 428c2ecf20Sopenharmony_ci#endif 438c2ecf20Sopenharmony_ci#if (DLM_LOCK_CW != LKM_CWMODE) 448c2ecf20Sopenharmony_ci# error Lock modes do not match 458c2ecf20Sopenharmony_ci#endif 468c2ecf20Sopenharmony_ci#if (DLM_LOCK_PR != LKM_PRMODE) 478c2ecf20Sopenharmony_ci# error Lock modes do not match 488c2ecf20Sopenharmony_ci#endif 498c2ecf20Sopenharmony_ci#if (DLM_LOCK_PW != LKM_PWMODE) 508c2ecf20Sopenharmony_ci# error Lock modes do not match 518c2ecf20Sopenharmony_ci#endif 528c2ecf20Sopenharmony_ci#if (DLM_LOCK_EX != LKM_EXMODE) 538c2ecf20Sopenharmony_ci# error Lock modes do not match 548c2ecf20Sopenharmony_ci#endif 558c2ecf20Sopenharmony_cistatic inline int mode_to_o2dlm(int mode) 568c2ecf20Sopenharmony_ci{ 578c2ecf20Sopenharmony_ci BUG_ON(mode > LKM_MAXMODE); 588c2ecf20Sopenharmony_ci 598c2ecf20Sopenharmony_ci return mode; 608c2ecf20Sopenharmony_ci} 618c2ecf20Sopenharmony_ci 628c2ecf20Sopenharmony_ci#define map_flag(_generic, _o2dlm) \ 638c2ecf20Sopenharmony_ci if (flags & (_generic)) { \ 648c2ecf20Sopenharmony_ci flags &= ~(_generic); \ 658c2ecf20Sopenharmony_ci o2dlm_flags |= (_o2dlm); \ 668c2ecf20Sopenharmony_ci } 678c2ecf20Sopenharmony_cistatic int flags_to_o2dlm(u32 flags) 688c2ecf20Sopenharmony_ci{ 698c2ecf20Sopenharmony_ci int o2dlm_flags = 0; 708c2ecf20Sopenharmony_ci 718c2ecf20Sopenharmony_ci map_flag(DLM_LKF_NOQUEUE, LKM_NOQUEUE); 728c2ecf20Sopenharmony_ci map_flag(DLM_LKF_CANCEL, LKM_CANCEL); 738c2ecf20Sopenharmony_ci map_flag(DLM_LKF_CONVERT, LKM_CONVERT); 748c2ecf20Sopenharmony_ci map_flag(DLM_LKF_VALBLK, LKM_VALBLK); 758c2ecf20Sopenharmony_ci map_flag(DLM_LKF_IVVALBLK, LKM_INVVALBLK); 768c2ecf20Sopenharmony_ci map_flag(DLM_LKF_ORPHAN, LKM_ORPHAN); 778c2ecf20Sopenharmony_ci map_flag(DLM_LKF_FORCEUNLOCK, LKM_FORCE); 788c2ecf20Sopenharmony_ci map_flag(DLM_LKF_TIMEOUT, LKM_TIMEOUT); 798c2ecf20Sopenharmony_ci map_flag(DLM_LKF_LOCAL, LKM_LOCAL); 808c2ecf20Sopenharmony_ci 818c2ecf20Sopenharmony_ci /* map_flag() should have cleared every flag passed in */ 828c2ecf20Sopenharmony_ci BUG_ON(flags != 0); 838c2ecf20Sopenharmony_ci 848c2ecf20Sopenharmony_ci return o2dlm_flags; 858c2ecf20Sopenharmony_ci} 868c2ecf20Sopenharmony_ci#undef map_flag 878c2ecf20Sopenharmony_ci 888c2ecf20Sopenharmony_ci/* 898c2ecf20Sopenharmony_ci * Map an o2dlm status to standard errno values. 908c2ecf20Sopenharmony_ci * 918c2ecf20Sopenharmony_ci * o2dlm only uses a handful of these, and returns even fewer to the 928c2ecf20Sopenharmony_ci * caller. Still, we try to assign sane values to each error. 938c2ecf20Sopenharmony_ci * 948c2ecf20Sopenharmony_ci * The following value pairs have special meanings to dlmglue, thus 958c2ecf20Sopenharmony_ci * the right hand side needs to stay unique - never duplicate the 968c2ecf20Sopenharmony_ci * mapping elsewhere in the table! 978c2ecf20Sopenharmony_ci * 988c2ecf20Sopenharmony_ci * DLM_NORMAL: 0 998c2ecf20Sopenharmony_ci * DLM_NOTQUEUED: -EAGAIN 1008c2ecf20Sopenharmony_ci * DLM_CANCELGRANT: -EBUSY 1018c2ecf20Sopenharmony_ci * DLM_CANCEL: -DLM_ECANCEL 1028c2ecf20Sopenharmony_ci */ 1038c2ecf20Sopenharmony_ci/* Keep in sync with dlmapi.h */ 1048c2ecf20Sopenharmony_cistatic int status_map[] = { 1058c2ecf20Sopenharmony_ci [DLM_NORMAL] = 0, /* Success */ 1068c2ecf20Sopenharmony_ci [DLM_GRANTED] = -EINVAL, 1078c2ecf20Sopenharmony_ci [DLM_DENIED] = -EACCES, 1088c2ecf20Sopenharmony_ci [DLM_DENIED_NOLOCKS] = -EACCES, 1098c2ecf20Sopenharmony_ci [DLM_WORKING] = -EACCES, 1108c2ecf20Sopenharmony_ci [DLM_BLOCKED] = -EINVAL, 1118c2ecf20Sopenharmony_ci [DLM_BLOCKED_ORPHAN] = -EINVAL, 1128c2ecf20Sopenharmony_ci [DLM_DENIED_GRACE_PERIOD] = -EACCES, 1138c2ecf20Sopenharmony_ci [DLM_SYSERR] = -ENOMEM, /* It is what it is */ 1148c2ecf20Sopenharmony_ci [DLM_NOSUPPORT] = -EPROTO, 1158c2ecf20Sopenharmony_ci [DLM_CANCELGRANT] = -EBUSY, /* Cancel after grant */ 1168c2ecf20Sopenharmony_ci [DLM_IVLOCKID] = -EINVAL, 1178c2ecf20Sopenharmony_ci [DLM_SYNC] = -EINVAL, 1188c2ecf20Sopenharmony_ci [DLM_BADTYPE] = -EINVAL, 1198c2ecf20Sopenharmony_ci [DLM_BADRESOURCE] = -EINVAL, 1208c2ecf20Sopenharmony_ci [DLM_MAXHANDLES] = -ENOMEM, 1218c2ecf20Sopenharmony_ci [DLM_NOCLINFO] = -EINVAL, 1228c2ecf20Sopenharmony_ci [DLM_NOLOCKMGR] = -EINVAL, 1238c2ecf20Sopenharmony_ci [DLM_NOPURGED] = -EINVAL, 1248c2ecf20Sopenharmony_ci [DLM_BADARGS] = -EINVAL, 1258c2ecf20Sopenharmony_ci [DLM_VOID] = -EINVAL, 1268c2ecf20Sopenharmony_ci [DLM_NOTQUEUED] = -EAGAIN, /* Trylock failed */ 1278c2ecf20Sopenharmony_ci [DLM_IVBUFLEN] = -EINVAL, 1288c2ecf20Sopenharmony_ci [DLM_CVTUNGRANT] = -EPERM, 1298c2ecf20Sopenharmony_ci [DLM_BADPARAM] = -EINVAL, 1308c2ecf20Sopenharmony_ci [DLM_VALNOTVALID] = -EINVAL, 1318c2ecf20Sopenharmony_ci [DLM_REJECTED] = -EPERM, 1328c2ecf20Sopenharmony_ci [DLM_ABORT] = -EINVAL, 1338c2ecf20Sopenharmony_ci [DLM_CANCEL] = -DLM_ECANCEL, /* Successful cancel */ 1348c2ecf20Sopenharmony_ci [DLM_IVRESHANDLE] = -EINVAL, 1358c2ecf20Sopenharmony_ci [DLM_DEADLOCK] = -EDEADLK, 1368c2ecf20Sopenharmony_ci [DLM_DENIED_NOASTS] = -EINVAL, 1378c2ecf20Sopenharmony_ci [DLM_FORWARD] = -EINVAL, 1388c2ecf20Sopenharmony_ci [DLM_TIMEOUT] = -ETIMEDOUT, 1398c2ecf20Sopenharmony_ci [DLM_IVGROUPID] = -EINVAL, 1408c2ecf20Sopenharmony_ci [DLM_VERS_CONFLICT] = -EOPNOTSUPP, 1418c2ecf20Sopenharmony_ci [DLM_BAD_DEVICE_PATH] = -ENOENT, 1428c2ecf20Sopenharmony_ci [DLM_NO_DEVICE_PERMISSION] = -EPERM, 1438c2ecf20Sopenharmony_ci [DLM_NO_CONTROL_DEVICE] = -ENOENT, 1448c2ecf20Sopenharmony_ci [DLM_RECOVERING] = -ENOTCONN, 1458c2ecf20Sopenharmony_ci [DLM_MIGRATING] = -ERESTART, 1468c2ecf20Sopenharmony_ci [DLM_MAXSTATS] = -EINVAL, 1478c2ecf20Sopenharmony_ci}; 1488c2ecf20Sopenharmony_ci 1498c2ecf20Sopenharmony_cistatic int dlm_status_to_errno(enum dlm_status status) 1508c2ecf20Sopenharmony_ci{ 1518c2ecf20Sopenharmony_ci BUG_ON(status < 0 || status >= ARRAY_SIZE(status_map)); 1528c2ecf20Sopenharmony_ci 1538c2ecf20Sopenharmony_ci return status_map[status]; 1548c2ecf20Sopenharmony_ci} 1558c2ecf20Sopenharmony_ci 1568c2ecf20Sopenharmony_cistatic void o2dlm_lock_ast_wrapper(void *astarg) 1578c2ecf20Sopenharmony_ci{ 1588c2ecf20Sopenharmony_ci struct ocfs2_dlm_lksb *lksb = astarg; 1598c2ecf20Sopenharmony_ci 1608c2ecf20Sopenharmony_ci lksb->lksb_conn->cc_proto->lp_lock_ast(lksb); 1618c2ecf20Sopenharmony_ci} 1628c2ecf20Sopenharmony_ci 1638c2ecf20Sopenharmony_cistatic void o2dlm_blocking_ast_wrapper(void *astarg, int level) 1648c2ecf20Sopenharmony_ci{ 1658c2ecf20Sopenharmony_ci struct ocfs2_dlm_lksb *lksb = astarg; 1668c2ecf20Sopenharmony_ci 1678c2ecf20Sopenharmony_ci lksb->lksb_conn->cc_proto->lp_blocking_ast(lksb, level); 1688c2ecf20Sopenharmony_ci} 1698c2ecf20Sopenharmony_ci 1708c2ecf20Sopenharmony_cistatic void o2dlm_unlock_ast_wrapper(void *astarg, enum dlm_status status) 1718c2ecf20Sopenharmony_ci{ 1728c2ecf20Sopenharmony_ci struct ocfs2_dlm_lksb *lksb = astarg; 1738c2ecf20Sopenharmony_ci int error = dlm_status_to_errno(status); 1748c2ecf20Sopenharmony_ci 1758c2ecf20Sopenharmony_ci /* 1768c2ecf20Sopenharmony_ci * In o2dlm, you can get both the lock_ast() for the lock being 1778c2ecf20Sopenharmony_ci * granted and the unlock_ast() for the CANCEL failing. A 1788c2ecf20Sopenharmony_ci * successful cancel sends DLM_NORMAL here. If the 1798c2ecf20Sopenharmony_ci * lock grant happened before the cancel arrived, you get 1808c2ecf20Sopenharmony_ci * DLM_CANCELGRANT. 1818c2ecf20Sopenharmony_ci * 1828c2ecf20Sopenharmony_ci * There's no need for the double-ast. If we see DLM_CANCELGRANT, 1838c2ecf20Sopenharmony_ci * we just ignore it. We expect the lock_ast() to handle the 1848c2ecf20Sopenharmony_ci * granted lock. 1858c2ecf20Sopenharmony_ci */ 1868c2ecf20Sopenharmony_ci if (status == DLM_CANCELGRANT) 1878c2ecf20Sopenharmony_ci return; 1888c2ecf20Sopenharmony_ci 1898c2ecf20Sopenharmony_ci lksb->lksb_conn->cc_proto->lp_unlock_ast(lksb, error); 1908c2ecf20Sopenharmony_ci} 1918c2ecf20Sopenharmony_ci 1928c2ecf20Sopenharmony_cistatic int o2cb_dlm_lock(struct ocfs2_cluster_connection *conn, 1938c2ecf20Sopenharmony_ci int mode, 1948c2ecf20Sopenharmony_ci struct ocfs2_dlm_lksb *lksb, 1958c2ecf20Sopenharmony_ci u32 flags, 1968c2ecf20Sopenharmony_ci void *name, 1978c2ecf20Sopenharmony_ci unsigned int namelen) 1988c2ecf20Sopenharmony_ci{ 1998c2ecf20Sopenharmony_ci enum dlm_status status; 2008c2ecf20Sopenharmony_ci int o2dlm_mode = mode_to_o2dlm(mode); 2018c2ecf20Sopenharmony_ci int o2dlm_flags = flags_to_o2dlm(flags); 2028c2ecf20Sopenharmony_ci int ret; 2038c2ecf20Sopenharmony_ci 2048c2ecf20Sopenharmony_ci status = dlmlock(conn->cc_lockspace, o2dlm_mode, &lksb->lksb_o2dlm, 2058c2ecf20Sopenharmony_ci o2dlm_flags, name, namelen, 2068c2ecf20Sopenharmony_ci o2dlm_lock_ast_wrapper, lksb, 2078c2ecf20Sopenharmony_ci o2dlm_blocking_ast_wrapper); 2088c2ecf20Sopenharmony_ci ret = dlm_status_to_errno(status); 2098c2ecf20Sopenharmony_ci return ret; 2108c2ecf20Sopenharmony_ci} 2118c2ecf20Sopenharmony_ci 2128c2ecf20Sopenharmony_cistatic int o2cb_dlm_unlock(struct ocfs2_cluster_connection *conn, 2138c2ecf20Sopenharmony_ci struct ocfs2_dlm_lksb *lksb, 2148c2ecf20Sopenharmony_ci u32 flags) 2158c2ecf20Sopenharmony_ci{ 2168c2ecf20Sopenharmony_ci enum dlm_status status; 2178c2ecf20Sopenharmony_ci int o2dlm_flags = flags_to_o2dlm(flags); 2188c2ecf20Sopenharmony_ci int ret; 2198c2ecf20Sopenharmony_ci 2208c2ecf20Sopenharmony_ci status = dlmunlock(conn->cc_lockspace, &lksb->lksb_o2dlm, 2218c2ecf20Sopenharmony_ci o2dlm_flags, o2dlm_unlock_ast_wrapper, lksb); 2228c2ecf20Sopenharmony_ci ret = dlm_status_to_errno(status); 2238c2ecf20Sopenharmony_ci return ret; 2248c2ecf20Sopenharmony_ci} 2258c2ecf20Sopenharmony_ci 2268c2ecf20Sopenharmony_cistatic int o2cb_dlm_lock_status(struct ocfs2_dlm_lksb *lksb) 2278c2ecf20Sopenharmony_ci{ 2288c2ecf20Sopenharmony_ci return dlm_status_to_errno(lksb->lksb_o2dlm.status); 2298c2ecf20Sopenharmony_ci} 2308c2ecf20Sopenharmony_ci 2318c2ecf20Sopenharmony_ci/* 2328c2ecf20Sopenharmony_ci * o2dlm aways has a "valid" LVB. If the dlm loses track of the LVB 2338c2ecf20Sopenharmony_ci * contents, it will zero out the LVB. Thus the caller can always trust 2348c2ecf20Sopenharmony_ci * the contents. 2358c2ecf20Sopenharmony_ci */ 2368c2ecf20Sopenharmony_cistatic int o2cb_dlm_lvb_valid(struct ocfs2_dlm_lksb *lksb) 2378c2ecf20Sopenharmony_ci{ 2388c2ecf20Sopenharmony_ci return 1; 2398c2ecf20Sopenharmony_ci} 2408c2ecf20Sopenharmony_ci 2418c2ecf20Sopenharmony_cistatic void *o2cb_dlm_lvb(struct ocfs2_dlm_lksb *lksb) 2428c2ecf20Sopenharmony_ci{ 2438c2ecf20Sopenharmony_ci return (void *)(lksb->lksb_o2dlm.lvb); 2448c2ecf20Sopenharmony_ci} 2458c2ecf20Sopenharmony_ci 2468c2ecf20Sopenharmony_cistatic void o2cb_dump_lksb(struct ocfs2_dlm_lksb *lksb) 2478c2ecf20Sopenharmony_ci{ 2488c2ecf20Sopenharmony_ci dlm_print_one_lock(lksb->lksb_o2dlm.lockid); 2498c2ecf20Sopenharmony_ci} 2508c2ecf20Sopenharmony_ci 2518c2ecf20Sopenharmony_ci/* 2528c2ecf20Sopenharmony_ci * Check if this node is heartbeating and is connected to all other 2538c2ecf20Sopenharmony_ci * heartbeating nodes. 2548c2ecf20Sopenharmony_ci */ 2558c2ecf20Sopenharmony_cistatic int o2cb_cluster_check(void) 2568c2ecf20Sopenharmony_ci{ 2578c2ecf20Sopenharmony_ci u8 node_num; 2588c2ecf20Sopenharmony_ci int i; 2598c2ecf20Sopenharmony_ci unsigned long hbmap[BITS_TO_LONGS(O2NM_MAX_NODES)]; 2608c2ecf20Sopenharmony_ci unsigned long netmap[BITS_TO_LONGS(O2NM_MAX_NODES)]; 2618c2ecf20Sopenharmony_ci 2628c2ecf20Sopenharmony_ci node_num = o2nm_this_node(); 2638c2ecf20Sopenharmony_ci if (node_num == O2NM_MAX_NODES) { 2648c2ecf20Sopenharmony_ci printk(KERN_ERR "o2cb: This node has not been configured.\n"); 2658c2ecf20Sopenharmony_ci return -EINVAL; 2668c2ecf20Sopenharmony_ci } 2678c2ecf20Sopenharmony_ci 2688c2ecf20Sopenharmony_ci /* 2698c2ecf20Sopenharmony_ci * o2dlm expects o2net sockets to be created. If not, then 2708c2ecf20Sopenharmony_ci * dlm_join_domain() fails with a stack of errors which are both cryptic 2718c2ecf20Sopenharmony_ci * and incomplete. The idea here is to detect upfront whether we have 2728c2ecf20Sopenharmony_ci * managed to connect to all nodes or not. If not, then list the nodes 2738c2ecf20Sopenharmony_ci * to allow the user to check the configuration (incorrect IP, firewall, 2748c2ecf20Sopenharmony_ci * etc.) Yes, this is racy. But its not the end of the world. 2758c2ecf20Sopenharmony_ci */ 2768c2ecf20Sopenharmony_ci#define O2CB_MAP_STABILIZE_COUNT 60 2778c2ecf20Sopenharmony_ci for (i = 0; i < O2CB_MAP_STABILIZE_COUNT; ++i) { 2788c2ecf20Sopenharmony_ci o2hb_fill_node_map(hbmap, sizeof(hbmap)); 2798c2ecf20Sopenharmony_ci if (!test_bit(node_num, hbmap)) { 2808c2ecf20Sopenharmony_ci printk(KERN_ERR "o2cb: %s heartbeat has not been " 2818c2ecf20Sopenharmony_ci "started.\n", (o2hb_global_heartbeat_active() ? 2828c2ecf20Sopenharmony_ci "Global" : "Local")); 2838c2ecf20Sopenharmony_ci return -EINVAL; 2848c2ecf20Sopenharmony_ci } 2858c2ecf20Sopenharmony_ci o2net_fill_node_map(netmap, sizeof(netmap)); 2868c2ecf20Sopenharmony_ci /* Force set the current node to allow easy compare */ 2878c2ecf20Sopenharmony_ci set_bit(node_num, netmap); 2888c2ecf20Sopenharmony_ci if (!memcmp(hbmap, netmap, sizeof(hbmap))) 2898c2ecf20Sopenharmony_ci return 0; 2908c2ecf20Sopenharmony_ci if (i < O2CB_MAP_STABILIZE_COUNT - 1) 2918c2ecf20Sopenharmony_ci msleep(1000); 2928c2ecf20Sopenharmony_ci } 2938c2ecf20Sopenharmony_ci 2948c2ecf20Sopenharmony_ci printk(KERN_ERR "o2cb: This node could not connect to nodes:"); 2958c2ecf20Sopenharmony_ci i = -1; 2968c2ecf20Sopenharmony_ci while ((i = find_next_bit(hbmap, O2NM_MAX_NODES, 2978c2ecf20Sopenharmony_ci i + 1)) < O2NM_MAX_NODES) { 2988c2ecf20Sopenharmony_ci if (!test_bit(i, netmap)) 2998c2ecf20Sopenharmony_ci printk(" %u", i); 3008c2ecf20Sopenharmony_ci } 3018c2ecf20Sopenharmony_ci printk(".\n"); 3028c2ecf20Sopenharmony_ci 3038c2ecf20Sopenharmony_ci return -ENOTCONN; 3048c2ecf20Sopenharmony_ci} 3058c2ecf20Sopenharmony_ci 3068c2ecf20Sopenharmony_ci/* 3078c2ecf20Sopenharmony_ci * Called from the dlm when it's about to evict a node. This is how the 3088c2ecf20Sopenharmony_ci * classic stack signals node death. 3098c2ecf20Sopenharmony_ci */ 3108c2ecf20Sopenharmony_cistatic void o2dlm_eviction_cb(int node_num, void *data) 3118c2ecf20Sopenharmony_ci{ 3128c2ecf20Sopenharmony_ci struct ocfs2_cluster_connection *conn = data; 3138c2ecf20Sopenharmony_ci 3148c2ecf20Sopenharmony_ci printk(KERN_NOTICE "o2cb: o2dlm has evicted node %d from domain %.*s\n", 3158c2ecf20Sopenharmony_ci node_num, conn->cc_namelen, conn->cc_name); 3168c2ecf20Sopenharmony_ci 3178c2ecf20Sopenharmony_ci conn->cc_recovery_handler(node_num, conn->cc_recovery_data); 3188c2ecf20Sopenharmony_ci} 3198c2ecf20Sopenharmony_ci 3208c2ecf20Sopenharmony_cistatic int o2cb_cluster_connect(struct ocfs2_cluster_connection *conn) 3218c2ecf20Sopenharmony_ci{ 3228c2ecf20Sopenharmony_ci int rc = 0; 3238c2ecf20Sopenharmony_ci u32 dlm_key; 3248c2ecf20Sopenharmony_ci struct dlm_ctxt *dlm; 3258c2ecf20Sopenharmony_ci struct o2dlm_private *priv; 3268c2ecf20Sopenharmony_ci struct dlm_protocol_version fs_version; 3278c2ecf20Sopenharmony_ci 3288c2ecf20Sopenharmony_ci BUG_ON(conn == NULL); 3298c2ecf20Sopenharmony_ci BUG_ON(conn->cc_proto == NULL); 3308c2ecf20Sopenharmony_ci 3318c2ecf20Sopenharmony_ci /* Ensure cluster stack is up and all nodes are connected */ 3328c2ecf20Sopenharmony_ci rc = o2cb_cluster_check(); 3338c2ecf20Sopenharmony_ci if (rc) { 3348c2ecf20Sopenharmony_ci printk(KERN_ERR "o2cb: Cluster check failed. Fix errors " 3358c2ecf20Sopenharmony_ci "before retrying.\n"); 3368c2ecf20Sopenharmony_ci goto out; 3378c2ecf20Sopenharmony_ci } 3388c2ecf20Sopenharmony_ci 3398c2ecf20Sopenharmony_ci priv = kzalloc(sizeof(struct o2dlm_private), GFP_KERNEL); 3408c2ecf20Sopenharmony_ci if (!priv) { 3418c2ecf20Sopenharmony_ci rc = -ENOMEM; 3428c2ecf20Sopenharmony_ci goto out_free; 3438c2ecf20Sopenharmony_ci } 3448c2ecf20Sopenharmony_ci 3458c2ecf20Sopenharmony_ci /* This just fills the structure in. It is safe to pass conn. */ 3468c2ecf20Sopenharmony_ci dlm_setup_eviction_cb(&priv->op_eviction_cb, o2dlm_eviction_cb, 3478c2ecf20Sopenharmony_ci conn); 3488c2ecf20Sopenharmony_ci 3498c2ecf20Sopenharmony_ci conn->cc_private = priv; 3508c2ecf20Sopenharmony_ci 3518c2ecf20Sopenharmony_ci /* used by the dlm code to make message headers unique, each 3528c2ecf20Sopenharmony_ci * node in this domain must agree on this. */ 3538c2ecf20Sopenharmony_ci dlm_key = crc32_le(0, conn->cc_name, conn->cc_namelen); 3548c2ecf20Sopenharmony_ci fs_version.pv_major = conn->cc_version.pv_major; 3558c2ecf20Sopenharmony_ci fs_version.pv_minor = conn->cc_version.pv_minor; 3568c2ecf20Sopenharmony_ci 3578c2ecf20Sopenharmony_ci dlm = dlm_register_domain(conn->cc_name, dlm_key, &fs_version); 3588c2ecf20Sopenharmony_ci if (IS_ERR(dlm)) { 3598c2ecf20Sopenharmony_ci rc = PTR_ERR(dlm); 3608c2ecf20Sopenharmony_ci mlog_errno(rc); 3618c2ecf20Sopenharmony_ci goto out_free; 3628c2ecf20Sopenharmony_ci } 3638c2ecf20Sopenharmony_ci 3648c2ecf20Sopenharmony_ci conn->cc_version.pv_major = fs_version.pv_major; 3658c2ecf20Sopenharmony_ci conn->cc_version.pv_minor = fs_version.pv_minor; 3668c2ecf20Sopenharmony_ci conn->cc_lockspace = dlm; 3678c2ecf20Sopenharmony_ci 3688c2ecf20Sopenharmony_ci dlm_register_eviction_cb(dlm, &priv->op_eviction_cb); 3698c2ecf20Sopenharmony_ci 3708c2ecf20Sopenharmony_ciout_free: 3718c2ecf20Sopenharmony_ci if (rc) 3728c2ecf20Sopenharmony_ci kfree(conn->cc_private); 3738c2ecf20Sopenharmony_ci 3748c2ecf20Sopenharmony_ciout: 3758c2ecf20Sopenharmony_ci return rc; 3768c2ecf20Sopenharmony_ci} 3778c2ecf20Sopenharmony_ci 3788c2ecf20Sopenharmony_cistatic int o2cb_cluster_disconnect(struct ocfs2_cluster_connection *conn) 3798c2ecf20Sopenharmony_ci{ 3808c2ecf20Sopenharmony_ci struct dlm_ctxt *dlm = conn->cc_lockspace; 3818c2ecf20Sopenharmony_ci struct o2dlm_private *priv = conn->cc_private; 3828c2ecf20Sopenharmony_ci 3838c2ecf20Sopenharmony_ci dlm_unregister_eviction_cb(&priv->op_eviction_cb); 3848c2ecf20Sopenharmony_ci conn->cc_private = NULL; 3858c2ecf20Sopenharmony_ci kfree(priv); 3868c2ecf20Sopenharmony_ci 3878c2ecf20Sopenharmony_ci dlm_unregister_domain(dlm); 3888c2ecf20Sopenharmony_ci conn->cc_lockspace = NULL; 3898c2ecf20Sopenharmony_ci 3908c2ecf20Sopenharmony_ci return 0; 3918c2ecf20Sopenharmony_ci} 3928c2ecf20Sopenharmony_ci 3938c2ecf20Sopenharmony_cistatic int o2cb_cluster_this_node(struct ocfs2_cluster_connection *conn, 3948c2ecf20Sopenharmony_ci unsigned int *node) 3958c2ecf20Sopenharmony_ci{ 3968c2ecf20Sopenharmony_ci int node_num; 3978c2ecf20Sopenharmony_ci 3988c2ecf20Sopenharmony_ci node_num = o2nm_this_node(); 3998c2ecf20Sopenharmony_ci if (node_num == O2NM_INVALID_NODE_NUM) 4008c2ecf20Sopenharmony_ci return -ENOENT; 4018c2ecf20Sopenharmony_ci 4028c2ecf20Sopenharmony_ci if (node_num >= O2NM_MAX_NODES) 4038c2ecf20Sopenharmony_ci return -EOVERFLOW; 4048c2ecf20Sopenharmony_ci 4058c2ecf20Sopenharmony_ci *node = node_num; 4068c2ecf20Sopenharmony_ci return 0; 4078c2ecf20Sopenharmony_ci} 4088c2ecf20Sopenharmony_ci 4098c2ecf20Sopenharmony_cistatic struct ocfs2_stack_operations o2cb_stack_ops = { 4108c2ecf20Sopenharmony_ci .connect = o2cb_cluster_connect, 4118c2ecf20Sopenharmony_ci .disconnect = o2cb_cluster_disconnect, 4128c2ecf20Sopenharmony_ci .this_node = o2cb_cluster_this_node, 4138c2ecf20Sopenharmony_ci .dlm_lock = o2cb_dlm_lock, 4148c2ecf20Sopenharmony_ci .dlm_unlock = o2cb_dlm_unlock, 4158c2ecf20Sopenharmony_ci .lock_status = o2cb_dlm_lock_status, 4168c2ecf20Sopenharmony_ci .lvb_valid = o2cb_dlm_lvb_valid, 4178c2ecf20Sopenharmony_ci .lock_lvb = o2cb_dlm_lvb, 4188c2ecf20Sopenharmony_ci .dump_lksb = o2cb_dump_lksb, 4198c2ecf20Sopenharmony_ci}; 4208c2ecf20Sopenharmony_ci 4218c2ecf20Sopenharmony_cistatic struct ocfs2_stack_plugin o2cb_stack = { 4228c2ecf20Sopenharmony_ci .sp_name = "o2cb", 4238c2ecf20Sopenharmony_ci .sp_ops = &o2cb_stack_ops, 4248c2ecf20Sopenharmony_ci .sp_owner = THIS_MODULE, 4258c2ecf20Sopenharmony_ci}; 4268c2ecf20Sopenharmony_ci 4278c2ecf20Sopenharmony_cistatic int __init o2cb_stack_init(void) 4288c2ecf20Sopenharmony_ci{ 4298c2ecf20Sopenharmony_ci return ocfs2_stack_glue_register(&o2cb_stack); 4308c2ecf20Sopenharmony_ci} 4318c2ecf20Sopenharmony_ci 4328c2ecf20Sopenharmony_cistatic void __exit o2cb_stack_exit(void) 4338c2ecf20Sopenharmony_ci{ 4348c2ecf20Sopenharmony_ci ocfs2_stack_glue_unregister(&o2cb_stack); 4358c2ecf20Sopenharmony_ci} 4368c2ecf20Sopenharmony_ci 4378c2ecf20Sopenharmony_ciMODULE_AUTHOR("Oracle"); 4388c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("ocfs2 driver for the classic o2cb stack"); 4398c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL"); 4408c2ecf20Sopenharmony_cimodule_init(o2cb_stack_init); 4418c2ecf20Sopenharmony_cimodule_exit(o2cb_stack_exit); 442