162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * stack_o2cb.c 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Code which interfaces ocfs2 with the o2cb stack. 662306a36Sopenharmony_ci * 762306a36Sopenharmony_ci * Copyright (C) 2007 Oracle. All rights reserved. 862306a36Sopenharmony_ci */ 962306a36Sopenharmony_ci 1062306a36Sopenharmony_ci#include <linux/kernel.h> 1162306a36Sopenharmony_ci#include <linux/crc32.h> 1262306a36Sopenharmony_ci#include <linux/slab.h> 1362306a36Sopenharmony_ci#include <linux/module.h> 1462306a36Sopenharmony_ci 1562306a36Sopenharmony_ci/* Needed for AOP_TRUNCATED_PAGE in mlog_errno() */ 1662306a36Sopenharmony_ci#include <linux/fs.h> 1762306a36Sopenharmony_ci 1862306a36Sopenharmony_ci#include "cluster/masklog.h" 1962306a36Sopenharmony_ci#include "cluster/nodemanager.h" 2062306a36Sopenharmony_ci#include "cluster/heartbeat.h" 2162306a36Sopenharmony_ci#include "cluster/tcp.h" 2262306a36Sopenharmony_ci 2362306a36Sopenharmony_ci#include "stackglue.h" 2462306a36Sopenharmony_ci 2562306a36Sopenharmony_cistruct o2dlm_private { 2662306a36Sopenharmony_ci struct dlm_eviction_cb op_eviction_cb; 2762306a36Sopenharmony_ci}; 2862306a36Sopenharmony_ci 2962306a36Sopenharmony_cistatic struct ocfs2_stack_plugin o2cb_stack; 3062306a36Sopenharmony_ci 3162306a36Sopenharmony_ci/* These should be identical */ 3262306a36Sopenharmony_ci#if (DLM_LOCK_IV != LKM_IVMODE) 3362306a36Sopenharmony_ci# error Lock modes do not match 3462306a36Sopenharmony_ci#endif 3562306a36Sopenharmony_ci#if (DLM_LOCK_NL != LKM_NLMODE) 3662306a36Sopenharmony_ci# error Lock modes do not match 3762306a36Sopenharmony_ci#endif 3862306a36Sopenharmony_ci#if (DLM_LOCK_CR != LKM_CRMODE) 3962306a36Sopenharmony_ci# error Lock modes do not match 4062306a36Sopenharmony_ci#endif 4162306a36Sopenharmony_ci#if (DLM_LOCK_CW != LKM_CWMODE) 4262306a36Sopenharmony_ci# error Lock modes do not match 4362306a36Sopenharmony_ci#endif 4462306a36Sopenharmony_ci#if (DLM_LOCK_PR != LKM_PRMODE) 4562306a36Sopenharmony_ci# error Lock modes do not match 4662306a36Sopenharmony_ci#endif 4762306a36Sopenharmony_ci#if (DLM_LOCK_PW != LKM_PWMODE) 4862306a36Sopenharmony_ci# error Lock modes do not match 4962306a36Sopenharmony_ci#endif 5062306a36Sopenharmony_ci#if (DLM_LOCK_EX != LKM_EXMODE) 5162306a36Sopenharmony_ci# error Lock modes do not match 5262306a36Sopenharmony_ci#endif 5362306a36Sopenharmony_cistatic inline int mode_to_o2dlm(int mode) 5462306a36Sopenharmony_ci{ 5562306a36Sopenharmony_ci BUG_ON(mode > LKM_MAXMODE); 5662306a36Sopenharmony_ci 5762306a36Sopenharmony_ci return mode; 5862306a36Sopenharmony_ci} 5962306a36Sopenharmony_ci 6062306a36Sopenharmony_cistatic int flags_to_o2dlm(u32 flags) 6162306a36Sopenharmony_ci{ 6262306a36Sopenharmony_ci int o2dlm_flags = 0; 6362306a36Sopenharmony_ci 6462306a36Sopenharmony_ci if (flags & DLM_LKF_NOQUEUE) 6562306a36Sopenharmony_ci o2dlm_flags |= LKM_NOQUEUE; 6662306a36Sopenharmony_ci if (flags & DLM_LKF_CANCEL) 6762306a36Sopenharmony_ci o2dlm_flags |= LKM_CANCEL; 6862306a36Sopenharmony_ci if (flags & DLM_LKF_CONVERT) 6962306a36Sopenharmony_ci o2dlm_flags |= LKM_CONVERT; 7062306a36Sopenharmony_ci if (flags & DLM_LKF_VALBLK) 7162306a36Sopenharmony_ci o2dlm_flags |= LKM_VALBLK; 7262306a36Sopenharmony_ci if (flags & DLM_LKF_IVVALBLK) 7362306a36Sopenharmony_ci o2dlm_flags |= LKM_INVVALBLK; 7462306a36Sopenharmony_ci if (flags & DLM_LKF_ORPHAN) 7562306a36Sopenharmony_ci o2dlm_flags |= LKM_ORPHAN; 7662306a36Sopenharmony_ci if (flags & DLM_LKF_FORCEUNLOCK) 7762306a36Sopenharmony_ci o2dlm_flags |= LKM_FORCE; 7862306a36Sopenharmony_ci if (flags & DLM_LKF_TIMEOUT) 7962306a36Sopenharmony_ci o2dlm_flags |= LKM_TIMEOUT; 8062306a36Sopenharmony_ci if (flags & DLM_LKF_LOCAL) 8162306a36Sopenharmony_ci o2dlm_flags |= LKM_LOCAL; 8262306a36Sopenharmony_ci 8362306a36Sopenharmony_ci return o2dlm_flags; 8462306a36Sopenharmony_ci} 8562306a36Sopenharmony_ci 8662306a36Sopenharmony_ci/* 8762306a36Sopenharmony_ci * Map an o2dlm status to standard errno values. 8862306a36Sopenharmony_ci * 8962306a36Sopenharmony_ci * o2dlm only uses a handful of these, and returns even fewer to the 9062306a36Sopenharmony_ci * caller. Still, we try to assign sane values to each error. 9162306a36Sopenharmony_ci * 9262306a36Sopenharmony_ci * The following value pairs have special meanings to dlmglue, thus 9362306a36Sopenharmony_ci * the right hand side needs to stay unique - never duplicate the 9462306a36Sopenharmony_ci * mapping elsewhere in the table! 9562306a36Sopenharmony_ci * 9662306a36Sopenharmony_ci * DLM_NORMAL: 0 9762306a36Sopenharmony_ci * DLM_NOTQUEUED: -EAGAIN 9862306a36Sopenharmony_ci * DLM_CANCELGRANT: -EBUSY 9962306a36Sopenharmony_ci * DLM_CANCEL: -DLM_ECANCEL 10062306a36Sopenharmony_ci */ 10162306a36Sopenharmony_ci/* Keep in sync with dlmapi.h */ 10262306a36Sopenharmony_cistatic int status_map[] = { 10362306a36Sopenharmony_ci [DLM_NORMAL] = 0, /* Success */ 10462306a36Sopenharmony_ci [DLM_GRANTED] = -EINVAL, 10562306a36Sopenharmony_ci [DLM_DENIED] = -EACCES, 10662306a36Sopenharmony_ci [DLM_DENIED_NOLOCKS] = -EACCES, 10762306a36Sopenharmony_ci [DLM_WORKING] = -EACCES, 10862306a36Sopenharmony_ci [DLM_BLOCKED] = -EINVAL, 10962306a36Sopenharmony_ci [DLM_BLOCKED_ORPHAN] = -EINVAL, 11062306a36Sopenharmony_ci [DLM_DENIED_GRACE_PERIOD] = -EACCES, 11162306a36Sopenharmony_ci [DLM_SYSERR] = -ENOMEM, /* It is what it is */ 11262306a36Sopenharmony_ci [DLM_NOSUPPORT] = -EPROTO, 11362306a36Sopenharmony_ci [DLM_CANCELGRANT] = -EBUSY, /* Cancel after grant */ 11462306a36Sopenharmony_ci [DLM_IVLOCKID] = -EINVAL, 11562306a36Sopenharmony_ci [DLM_SYNC] = -EINVAL, 11662306a36Sopenharmony_ci [DLM_BADTYPE] = -EINVAL, 11762306a36Sopenharmony_ci [DLM_BADRESOURCE] = -EINVAL, 11862306a36Sopenharmony_ci [DLM_MAXHANDLES] = -ENOMEM, 11962306a36Sopenharmony_ci [DLM_NOCLINFO] = -EINVAL, 12062306a36Sopenharmony_ci [DLM_NOLOCKMGR] = -EINVAL, 12162306a36Sopenharmony_ci [DLM_NOPURGED] = -EINVAL, 12262306a36Sopenharmony_ci [DLM_BADARGS] = -EINVAL, 12362306a36Sopenharmony_ci [DLM_VOID] = -EINVAL, 12462306a36Sopenharmony_ci [DLM_NOTQUEUED] = -EAGAIN, /* Trylock failed */ 12562306a36Sopenharmony_ci [DLM_IVBUFLEN] = -EINVAL, 12662306a36Sopenharmony_ci [DLM_CVTUNGRANT] = -EPERM, 12762306a36Sopenharmony_ci [DLM_BADPARAM] = -EINVAL, 12862306a36Sopenharmony_ci [DLM_VALNOTVALID] = -EINVAL, 12962306a36Sopenharmony_ci [DLM_REJECTED] = -EPERM, 13062306a36Sopenharmony_ci [DLM_ABORT] = -EINVAL, 13162306a36Sopenharmony_ci [DLM_CANCEL] = -DLM_ECANCEL, /* Successful cancel */ 13262306a36Sopenharmony_ci [DLM_IVRESHANDLE] = -EINVAL, 13362306a36Sopenharmony_ci [DLM_DEADLOCK] = -EDEADLK, 13462306a36Sopenharmony_ci [DLM_DENIED_NOASTS] = -EINVAL, 13562306a36Sopenharmony_ci [DLM_FORWARD] = -EINVAL, 13662306a36Sopenharmony_ci [DLM_TIMEOUT] = -ETIMEDOUT, 13762306a36Sopenharmony_ci [DLM_IVGROUPID] = -EINVAL, 13862306a36Sopenharmony_ci [DLM_VERS_CONFLICT] = -EOPNOTSUPP, 13962306a36Sopenharmony_ci [DLM_BAD_DEVICE_PATH] = -ENOENT, 14062306a36Sopenharmony_ci [DLM_NO_DEVICE_PERMISSION] = -EPERM, 14162306a36Sopenharmony_ci [DLM_NO_CONTROL_DEVICE] = -ENOENT, 14262306a36Sopenharmony_ci [DLM_RECOVERING] = -ENOTCONN, 14362306a36Sopenharmony_ci [DLM_MIGRATING] = -ERESTART, 14462306a36Sopenharmony_ci [DLM_MAXSTATS] = -EINVAL, 14562306a36Sopenharmony_ci}; 14662306a36Sopenharmony_ci 14762306a36Sopenharmony_cistatic int dlm_status_to_errno(enum dlm_status status) 14862306a36Sopenharmony_ci{ 14962306a36Sopenharmony_ci BUG_ON(status < 0 || status >= ARRAY_SIZE(status_map)); 15062306a36Sopenharmony_ci 15162306a36Sopenharmony_ci return status_map[status]; 15262306a36Sopenharmony_ci} 15362306a36Sopenharmony_ci 15462306a36Sopenharmony_cistatic void o2dlm_lock_ast_wrapper(void *astarg) 15562306a36Sopenharmony_ci{ 15662306a36Sopenharmony_ci struct ocfs2_dlm_lksb *lksb = astarg; 15762306a36Sopenharmony_ci 15862306a36Sopenharmony_ci lksb->lksb_conn->cc_proto->lp_lock_ast(lksb); 15962306a36Sopenharmony_ci} 16062306a36Sopenharmony_ci 16162306a36Sopenharmony_cistatic void o2dlm_blocking_ast_wrapper(void *astarg, int level) 16262306a36Sopenharmony_ci{ 16362306a36Sopenharmony_ci struct ocfs2_dlm_lksb *lksb = astarg; 16462306a36Sopenharmony_ci 16562306a36Sopenharmony_ci lksb->lksb_conn->cc_proto->lp_blocking_ast(lksb, level); 16662306a36Sopenharmony_ci} 16762306a36Sopenharmony_ci 16862306a36Sopenharmony_cistatic void o2dlm_unlock_ast_wrapper(void *astarg, enum dlm_status status) 16962306a36Sopenharmony_ci{ 17062306a36Sopenharmony_ci struct ocfs2_dlm_lksb *lksb = astarg; 17162306a36Sopenharmony_ci int error = dlm_status_to_errno(status); 17262306a36Sopenharmony_ci 17362306a36Sopenharmony_ci /* 17462306a36Sopenharmony_ci * In o2dlm, you can get both the lock_ast() for the lock being 17562306a36Sopenharmony_ci * granted and the unlock_ast() for the CANCEL failing. A 17662306a36Sopenharmony_ci * successful cancel sends DLM_NORMAL here. If the 17762306a36Sopenharmony_ci * lock grant happened before the cancel arrived, you get 17862306a36Sopenharmony_ci * DLM_CANCELGRANT. 17962306a36Sopenharmony_ci * 18062306a36Sopenharmony_ci * There's no need for the double-ast. If we see DLM_CANCELGRANT, 18162306a36Sopenharmony_ci * we just ignore it. We expect the lock_ast() to handle the 18262306a36Sopenharmony_ci * granted lock. 18362306a36Sopenharmony_ci */ 18462306a36Sopenharmony_ci if (status == DLM_CANCELGRANT) 18562306a36Sopenharmony_ci return; 18662306a36Sopenharmony_ci 18762306a36Sopenharmony_ci lksb->lksb_conn->cc_proto->lp_unlock_ast(lksb, error); 18862306a36Sopenharmony_ci} 18962306a36Sopenharmony_ci 19062306a36Sopenharmony_cistatic int o2cb_dlm_lock(struct ocfs2_cluster_connection *conn, 19162306a36Sopenharmony_ci int mode, 19262306a36Sopenharmony_ci struct ocfs2_dlm_lksb *lksb, 19362306a36Sopenharmony_ci u32 flags, 19462306a36Sopenharmony_ci void *name, 19562306a36Sopenharmony_ci unsigned int namelen) 19662306a36Sopenharmony_ci{ 19762306a36Sopenharmony_ci enum dlm_status status; 19862306a36Sopenharmony_ci int o2dlm_mode = mode_to_o2dlm(mode); 19962306a36Sopenharmony_ci int o2dlm_flags = flags_to_o2dlm(flags); 20062306a36Sopenharmony_ci int ret; 20162306a36Sopenharmony_ci 20262306a36Sopenharmony_ci status = dlmlock(conn->cc_lockspace, o2dlm_mode, &lksb->lksb_o2dlm, 20362306a36Sopenharmony_ci o2dlm_flags, name, namelen, 20462306a36Sopenharmony_ci o2dlm_lock_ast_wrapper, lksb, 20562306a36Sopenharmony_ci o2dlm_blocking_ast_wrapper); 20662306a36Sopenharmony_ci ret = dlm_status_to_errno(status); 20762306a36Sopenharmony_ci return ret; 20862306a36Sopenharmony_ci} 20962306a36Sopenharmony_ci 21062306a36Sopenharmony_cistatic int o2cb_dlm_unlock(struct ocfs2_cluster_connection *conn, 21162306a36Sopenharmony_ci struct ocfs2_dlm_lksb *lksb, 21262306a36Sopenharmony_ci u32 flags) 21362306a36Sopenharmony_ci{ 21462306a36Sopenharmony_ci enum dlm_status status; 21562306a36Sopenharmony_ci int o2dlm_flags = flags_to_o2dlm(flags); 21662306a36Sopenharmony_ci int ret; 21762306a36Sopenharmony_ci 21862306a36Sopenharmony_ci status = dlmunlock(conn->cc_lockspace, &lksb->lksb_o2dlm, 21962306a36Sopenharmony_ci o2dlm_flags, o2dlm_unlock_ast_wrapper, lksb); 22062306a36Sopenharmony_ci ret = dlm_status_to_errno(status); 22162306a36Sopenharmony_ci return ret; 22262306a36Sopenharmony_ci} 22362306a36Sopenharmony_ci 22462306a36Sopenharmony_cistatic int o2cb_dlm_lock_status(struct ocfs2_dlm_lksb *lksb) 22562306a36Sopenharmony_ci{ 22662306a36Sopenharmony_ci return dlm_status_to_errno(lksb->lksb_o2dlm.status); 22762306a36Sopenharmony_ci} 22862306a36Sopenharmony_ci 22962306a36Sopenharmony_ci/* 23062306a36Sopenharmony_ci * o2dlm aways has a "valid" LVB. If the dlm loses track of the LVB 23162306a36Sopenharmony_ci * contents, it will zero out the LVB. Thus the caller can always trust 23262306a36Sopenharmony_ci * the contents. 23362306a36Sopenharmony_ci */ 23462306a36Sopenharmony_cistatic int o2cb_dlm_lvb_valid(struct ocfs2_dlm_lksb *lksb) 23562306a36Sopenharmony_ci{ 23662306a36Sopenharmony_ci return 1; 23762306a36Sopenharmony_ci} 23862306a36Sopenharmony_ci 23962306a36Sopenharmony_cistatic void *o2cb_dlm_lvb(struct ocfs2_dlm_lksb *lksb) 24062306a36Sopenharmony_ci{ 24162306a36Sopenharmony_ci return (void *)(lksb->lksb_o2dlm.lvb); 24262306a36Sopenharmony_ci} 24362306a36Sopenharmony_ci 24462306a36Sopenharmony_cistatic void o2cb_dump_lksb(struct ocfs2_dlm_lksb *lksb) 24562306a36Sopenharmony_ci{ 24662306a36Sopenharmony_ci dlm_print_one_lock(lksb->lksb_o2dlm.lockid); 24762306a36Sopenharmony_ci} 24862306a36Sopenharmony_ci 24962306a36Sopenharmony_ci/* 25062306a36Sopenharmony_ci * Check if this node is heartbeating and is connected to all other 25162306a36Sopenharmony_ci * heartbeating nodes. 25262306a36Sopenharmony_ci */ 25362306a36Sopenharmony_cistatic int o2cb_cluster_check(void) 25462306a36Sopenharmony_ci{ 25562306a36Sopenharmony_ci u8 node_num; 25662306a36Sopenharmony_ci int i; 25762306a36Sopenharmony_ci unsigned long hbmap[BITS_TO_LONGS(O2NM_MAX_NODES)]; 25862306a36Sopenharmony_ci unsigned long netmap[BITS_TO_LONGS(O2NM_MAX_NODES)]; 25962306a36Sopenharmony_ci 26062306a36Sopenharmony_ci node_num = o2nm_this_node(); 26162306a36Sopenharmony_ci if (node_num == O2NM_MAX_NODES) { 26262306a36Sopenharmony_ci printk(KERN_ERR "o2cb: This node has not been configured.\n"); 26362306a36Sopenharmony_ci return -EINVAL; 26462306a36Sopenharmony_ci } 26562306a36Sopenharmony_ci 26662306a36Sopenharmony_ci /* 26762306a36Sopenharmony_ci * o2dlm expects o2net sockets to be created. If not, then 26862306a36Sopenharmony_ci * dlm_join_domain() fails with a stack of errors which are both cryptic 26962306a36Sopenharmony_ci * and incomplete. The idea here is to detect upfront whether we have 27062306a36Sopenharmony_ci * managed to connect to all nodes or not. If not, then list the nodes 27162306a36Sopenharmony_ci * to allow the user to check the configuration (incorrect IP, firewall, 27262306a36Sopenharmony_ci * etc.) Yes, this is racy. But its not the end of the world. 27362306a36Sopenharmony_ci */ 27462306a36Sopenharmony_ci#define O2CB_MAP_STABILIZE_COUNT 60 27562306a36Sopenharmony_ci for (i = 0; i < O2CB_MAP_STABILIZE_COUNT; ++i) { 27662306a36Sopenharmony_ci o2hb_fill_node_map(hbmap, O2NM_MAX_NODES); 27762306a36Sopenharmony_ci if (!test_bit(node_num, hbmap)) { 27862306a36Sopenharmony_ci printk(KERN_ERR "o2cb: %s heartbeat has not been " 27962306a36Sopenharmony_ci "started.\n", (o2hb_global_heartbeat_active() ? 28062306a36Sopenharmony_ci "Global" : "Local")); 28162306a36Sopenharmony_ci return -EINVAL; 28262306a36Sopenharmony_ci } 28362306a36Sopenharmony_ci o2net_fill_node_map(netmap, O2NM_MAX_NODES); 28462306a36Sopenharmony_ci /* Force set the current node to allow easy compare */ 28562306a36Sopenharmony_ci set_bit(node_num, netmap); 28662306a36Sopenharmony_ci if (bitmap_equal(hbmap, netmap, O2NM_MAX_NODES)) 28762306a36Sopenharmony_ci return 0; 28862306a36Sopenharmony_ci if (i < O2CB_MAP_STABILIZE_COUNT - 1) 28962306a36Sopenharmony_ci msleep(1000); 29062306a36Sopenharmony_ci } 29162306a36Sopenharmony_ci 29262306a36Sopenharmony_ci printk(KERN_ERR "o2cb: This node could not connect to nodes:"); 29362306a36Sopenharmony_ci i = -1; 29462306a36Sopenharmony_ci while ((i = find_next_bit(hbmap, O2NM_MAX_NODES, 29562306a36Sopenharmony_ci i + 1)) < O2NM_MAX_NODES) { 29662306a36Sopenharmony_ci if (!test_bit(i, netmap)) 29762306a36Sopenharmony_ci printk(" %u", i); 29862306a36Sopenharmony_ci } 29962306a36Sopenharmony_ci printk(".\n"); 30062306a36Sopenharmony_ci 30162306a36Sopenharmony_ci return -ENOTCONN; 30262306a36Sopenharmony_ci} 30362306a36Sopenharmony_ci 30462306a36Sopenharmony_ci/* 30562306a36Sopenharmony_ci * Called from the dlm when it's about to evict a node. This is how the 30662306a36Sopenharmony_ci * classic stack signals node death. 30762306a36Sopenharmony_ci */ 30862306a36Sopenharmony_cistatic void o2dlm_eviction_cb(int node_num, void *data) 30962306a36Sopenharmony_ci{ 31062306a36Sopenharmony_ci struct ocfs2_cluster_connection *conn = data; 31162306a36Sopenharmony_ci 31262306a36Sopenharmony_ci printk(KERN_NOTICE "o2cb: o2dlm has evicted node %d from domain %.*s\n", 31362306a36Sopenharmony_ci node_num, conn->cc_namelen, conn->cc_name); 31462306a36Sopenharmony_ci 31562306a36Sopenharmony_ci conn->cc_recovery_handler(node_num, conn->cc_recovery_data); 31662306a36Sopenharmony_ci} 31762306a36Sopenharmony_ci 31862306a36Sopenharmony_cistatic int o2cb_cluster_connect(struct ocfs2_cluster_connection *conn) 31962306a36Sopenharmony_ci{ 32062306a36Sopenharmony_ci int rc = 0; 32162306a36Sopenharmony_ci u32 dlm_key; 32262306a36Sopenharmony_ci struct dlm_ctxt *dlm; 32362306a36Sopenharmony_ci struct o2dlm_private *priv; 32462306a36Sopenharmony_ci struct dlm_protocol_version fs_version; 32562306a36Sopenharmony_ci 32662306a36Sopenharmony_ci BUG_ON(conn == NULL); 32762306a36Sopenharmony_ci BUG_ON(conn->cc_proto == NULL); 32862306a36Sopenharmony_ci 32962306a36Sopenharmony_ci /* Ensure cluster stack is up and all nodes are connected */ 33062306a36Sopenharmony_ci rc = o2cb_cluster_check(); 33162306a36Sopenharmony_ci if (rc) { 33262306a36Sopenharmony_ci printk(KERN_ERR "o2cb: Cluster check failed. Fix errors " 33362306a36Sopenharmony_ci "before retrying.\n"); 33462306a36Sopenharmony_ci goto out; 33562306a36Sopenharmony_ci } 33662306a36Sopenharmony_ci 33762306a36Sopenharmony_ci priv = kzalloc(sizeof(struct o2dlm_private), GFP_KERNEL); 33862306a36Sopenharmony_ci if (!priv) { 33962306a36Sopenharmony_ci rc = -ENOMEM; 34062306a36Sopenharmony_ci goto out_free; 34162306a36Sopenharmony_ci } 34262306a36Sopenharmony_ci 34362306a36Sopenharmony_ci /* This just fills the structure in. It is safe to pass conn. */ 34462306a36Sopenharmony_ci dlm_setup_eviction_cb(&priv->op_eviction_cb, o2dlm_eviction_cb, 34562306a36Sopenharmony_ci conn); 34662306a36Sopenharmony_ci 34762306a36Sopenharmony_ci conn->cc_private = priv; 34862306a36Sopenharmony_ci 34962306a36Sopenharmony_ci /* used by the dlm code to make message headers unique, each 35062306a36Sopenharmony_ci * node in this domain must agree on this. */ 35162306a36Sopenharmony_ci dlm_key = crc32_le(0, conn->cc_name, conn->cc_namelen); 35262306a36Sopenharmony_ci fs_version.pv_major = conn->cc_version.pv_major; 35362306a36Sopenharmony_ci fs_version.pv_minor = conn->cc_version.pv_minor; 35462306a36Sopenharmony_ci 35562306a36Sopenharmony_ci dlm = dlm_register_domain(conn->cc_name, dlm_key, &fs_version); 35662306a36Sopenharmony_ci if (IS_ERR(dlm)) { 35762306a36Sopenharmony_ci rc = PTR_ERR(dlm); 35862306a36Sopenharmony_ci mlog_errno(rc); 35962306a36Sopenharmony_ci goto out_free; 36062306a36Sopenharmony_ci } 36162306a36Sopenharmony_ci 36262306a36Sopenharmony_ci conn->cc_version.pv_major = fs_version.pv_major; 36362306a36Sopenharmony_ci conn->cc_version.pv_minor = fs_version.pv_minor; 36462306a36Sopenharmony_ci conn->cc_lockspace = dlm; 36562306a36Sopenharmony_ci 36662306a36Sopenharmony_ci dlm_register_eviction_cb(dlm, &priv->op_eviction_cb); 36762306a36Sopenharmony_ci 36862306a36Sopenharmony_ciout_free: 36962306a36Sopenharmony_ci if (rc) 37062306a36Sopenharmony_ci kfree(conn->cc_private); 37162306a36Sopenharmony_ci 37262306a36Sopenharmony_ciout: 37362306a36Sopenharmony_ci return rc; 37462306a36Sopenharmony_ci} 37562306a36Sopenharmony_ci 37662306a36Sopenharmony_cistatic int o2cb_cluster_disconnect(struct ocfs2_cluster_connection *conn) 37762306a36Sopenharmony_ci{ 37862306a36Sopenharmony_ci struct dlm_ctxt *dlm = conn->cc_lockspace; 37962306a36Sopenharmony_ci struct o2dlm_private *priv = conn->cc_private; 38062306a36Sopenharmony_ci 38162306a36Sopenharmony_ci dlm_unregister_eviction_cb(&priv->op_eviction_cb); 38262306a36Sopenharmony_ci conn->cc_private = NULL; 38362306a36Sopenharmony_ci kfree(priv); 38462306a36Sopenharmony_ci 38562306a36Sopenharmony_ci dlm_unregister_domain(dlm); 38662306a36Sopenharmony_ci conn->cc_lockspace = NULL; 38762306a36Sopenharmony_ci 38862306a36Sopenharmony_ci return 0; 38962306a36Sopenharmony_ci} 39062306a36Sopenharmony_ci 39162306a36Sopenharmony_cistatic int o2cb_cluster_this_node(struct ocfs2_cluster_connection *conn, 39262306a36Sopenharmony_ci unsigned int *node) 39362306a36Sopenharmony_ci{ 39462306a36Sopenharmony_ci int node_num; 39562306a36Sopenharmony_ci 39662306a36Sopenharmony_ci node_num = o2nm_this_node(); 39762306a36Sopenharmony_ci if (node_num == O2NM_INVALID_NODE_NUM) 39862306a36Sopenharmony_ci return -ENOENT; 39962306a36Sopenharmony_ci 40062306a36Sopenharmony_ci if (node_num >= O2NM_MAX_NODES) 40162306a36Sopenharmony_ci return -EOVERFLOW; 40262306a36Sopenharmony_ci 40362306a36Sopenharmony_ci *node = node_num; 40462306a36Sopenharmony_ci return 0; 40562306a36Sopenharmony_ci} 40662306a36Sopenharmony_ci 40762306a36Sopenharmony_cistatic struct ocfs2_stack_operations o2cb_stack_ops = { 40862306a36Sopenharmony_ci .connect = o2cb_cluster_connect, 40962306a36Sopenharmony_ci .disconnect = o2cb_cluster_disconnect, 41062306a36Sopenharmony_ci .this_node = o2cb_cluster_this_node, 41162306a36Sopenharmony_ci .dlm_lock = o2cb_dlm_lock, 41262306a36Sopenharmony_ci .dlm_unlock = o2cb_dlm_unlock, 41362306a36Sopenharmony_ci .lock_status = o2cb_dlm_lock_status, 41462306a36Sopenharmony_ci .lvb_valid = o2cb_dlm_lvb_valid, 41562306a36Sopenharmony_ci .lock_lvb = o2cb_dlm_lvb, 41662306a36Sopenharmony_ci .dump_lksb = o2cb_dump_lksb, 41762306a36Sopenharmony_ci}; 41862306a36Sopenharmony_ci 41962306a36Sopenharmony_cistatic struct ocfs2_stack_plugin o2cb_stack = { 42062306a36Sopenharmony_ci .sp_name = "o2cb", 42162306a36Sopenharmony_ci .sp_ops = &o2cb_stack_ops, 42262306a36Sopenharmony_ci .sp_owner = THIS_MODULE, 42362306a36Sopenharmony_ci}; 42462306a36Sopenharmony_ci 42562306a36Sopenharmony_cistatic int __init o2cb_stack_init(void) 42662306a36Sopenharmony_ci{ 42762306a36Sopenharmony_ci return ocfs2_stack_glue_register(&o2cb_stack); 42862306a36Sopenharmony_ci} 42962306a36Sopenharmony_ci 43062306a36Sopenharmony_cistatic void __exit o2cb_stack_exit(void) 43162306a36Sopenharmony_ci{ 43262306a36Sopenharmony_ci ocfs2_stack_glue_unregister(&o2cb_stack); 43362306a36Sopenharmony_ci} 43462306a36Sopenharmony_ci 43562306a36Sopenharmony_ciMODULE_AUTHOR("Oracle"); 43662306a36Sopenharmony_ciMODULE_DESCRIPTION("ocfs2 driver for the classic o2cb stack"); 43762306a36Sopenharmony_ciMODULE_LICENSE("GPL"); 43862306a36Sopenharmony_cimodule_init(o2cb_stack_init); 43962306a36Sopenharmony_cimodule_exit(o2cb_stack_exit); 440