1e3dad42bSJoel Becker /* -*- mode: c; c-basic-offset: 8; -*- 2e3dad42bSJoel Becker * vim: noexpandtab sw=8 ts=8 sts=0: 3e3dad42bSJoel Becker * 4e3dad42bSJoel Becker * stack_o2cb.c 5e3dad42bSJoel Becker * 6e3dad42bSJoel Becker * Code which interfaces ocfs2 with the o2cb stack. 7e3dad42bSJoel Becker * 8e3dad42bSJoel Becker * Copyright (C) 2007 Oracle. All rights reserved. 9e3dad42bSJoel Becker * 10e3dad42bSJoel Becker * This program is free software; you can redistribute it and/or 11e3dad42bSJoel Becker * modify it under the terms of the GNU General Public 12e3dad42bSJoel Becker * License as published by the Free Software Foundation, version 2. 13e3dad42bSJoel Becker * 14e3dad42bSJoel Becker * This program is distributed in the hope that it will be useful, 15e3dad42bSJoel Becker * but WITHOUT ANY WARRANTY; without even the implied warranty of 16e3dad42bSJoel Becker * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 17e3dad42bSJoel Becker * General Public License for more details. 18e3dad42bSJoel Becker */ 19e3dad42bSJoel Becker 208a57a9ddSRoel Kluin #include <linux/kernel.h> 21e3dad42bSJoel Becker #include <linux/crc32.h> 225a0e3ad6STejun Heo #include <linux/slab.h> 23286eaa95SJoel Becker #include <linux/module.h> 24e3dad42bSJoel Becker 25e3dad42bSJoel Becker /* Needed for AOP_TRUNCATED_PAGE in mlog_errno() */ 26e3dad42bSJoel Becker #include <linux/fs.h> 27e3dad42bSJoel Becker 28e3dad42bSJoel Becker #include "cluster/masklog.h" 29e3dad42bSJoel Becker #include "cluster/nodemanager.h" 30e3dad42bSJoel Becker #include "cluster/heartbeat.h" 316b27f62fSSunil Mushran #include "cluster/tcp.h" 32e3dad42bSJoel Becker 33e3dad42bSJoel Becker #include "stackglue.h" 34e3dad42bSJoel Becker 35e3dad42bSJoel Becker struct o2dlm_private { 36e3dad42bSJoel Becker struct dlm_eviction_cb op_eviction_cb; 37e3dad42bSJoel Becker }; 38e3dad42bSJoel Becker 39286eaa95SJoel Becker static struct ocfs2_stack_plugin o2cb_stack; 40286eaa95SJoel Becker 41e3dad42bSJoel Becker /* These should be identical */ 42e3dad42bSJoel Becker #if (DLM_LOCK_IV != LKM_IVMODE) 43e3dad42bSJoel Becker # error Lock modes do not match 44e3dad42bSJoel Becker #endif 45e3dad42bSJoel Becker #if (DLM_LOCK_NL != LKM_NLMODE) 46e3dad42bSJoel Becker # error Lock modes do not match 47e3dad42bSJoel Becker #endif 48e3dad42bSJoel Becker #if (DLM_LOCK_CR != LKM_CRMODE) 49e3dad42bSJoel Becker # error Lock modes do not match 50e3dad42bSJoel Becker #endif 51e3dad42bSJoel Becker #if (DLM_LOCK_CW != LKM_CWMODE) 52e3dad42bSJoel Becker # error Lock modes do not match 53e3dad42bSJoel Becker #endif 54e3dad42bSJoel Becker #if (DLM_LOCK_PR != LKM_PRMODE) 55e3dad42bSJoel Becker # error Lock modes do not match 56e3dad42bSJoel Becker #endif 57e3dad42bSJoel Becker #if (DLM_LOCK_PW != LKM_PWMODE) 58e3dad42bSJoel Becker # error Lock modes do not match 59e3dad42bSJoel Becker #endif 60e3dad42bSJoel Becker #if (DLM_LOCK_EX != LKM_EXMODE) 61e3dad42bSJoel Becker # error Lock modes do not match 62e3dad42bSJoel Becker #endif 63e3dad42bSJoel Becker static inline int mode_to_o2dlm(int mode) 64e3dad42bSJoel Becker { 65e3dad42bSJoel Becker BUG_ON(mode > LKM_MAXMODE); 66e3dad42bSJoel Becker 67e3dad42bSJoel Becker return mode; 68e3dad42bSJoel Becker } 69e3dad42bSJoel Becker 70e3dad42bSJoel Becker #define map_flag(_generic, _o2dlm) \ 71e3dad42bSJoel Becker if (flags & (_generic)) { \ 72e3dad42bSJoel Becker flags &= ~(_generic); \ 73e3dad42bSJoel Becker o2dlm_flags |= (_o2dlm); \ 74e3dad42bSJoel Becker } 75e3dad42bSJoel Becker static int flags_to_o2dlm(u32 flags) 76e3dad42bSJoel Becker { 77e3dad42bSJoel Becker int o2dlm_flags = 0; 78e3dad42bSJoel Becker 79e3dad42bSJoel Becker map_flag(DLM_LKF_NOQUEUE, LKM_NOQUEUE); 80e3dad42bSJoel Becker map_flag(DLM_LKF_CANCEL, LKM_CANCEL); 81e3dad42bSJoel Becker map_flag(DLM_LKF_CONVERT, LKM_CONVERT); 82e3dad42bSJoel Becker map_flag(DLM_LKF_VALBLK, LKM_VALBLK); 83e3dad42bSJoel Becker map_flag(DLM_LKF_IVVALBLK, LKM_INVVALBLK); 84e3dad42bSJoel Becker map_flag(DLM_LKF_ORPHAN, LKM_ORPHAN); 85e3dad42bSJoel Becker map_flag(DLM_LKF_FORCEUNLOCK, LKM_FORCE); 86e3dad42bSJoel Becker map_flag(DLM_LKF_TIMEOUT, LKM_TIMEOUT); 87e3dad42bSJoel Becker map_flag(DLM_LKF_LOCAL, LKM_LOCAL); 88e3dad42bSJoel Becker 89e3dad42bSJoel Becker /* map_flag() should have cleared every flag passed in */ 90e3dad42bSJoel Becker BUG_ON(flags != 0); 91e3dad42bSJoel Becker 92e3dad42bSJoel Becker return o2dlm_flags; 93e3dad42bSJoel Becker } 94e3dad42bSJoel Becker #undef map_flag 95e3dad42bSJoel Becker 96e3dad42bSJoel Becker /* 97e3dad42bSJoel Becker * Map an o2dlm status to standard errno values. 98e3dad42bSJoel Becker * 99e3dad42bSJoel Becker * o2dlm only uses a handful of these, and returns even fewer to the 100e3dad42bSJoel Becker * caller. Still, we try to assign sane values to each error. 101e3dad42bSJoel Becker * 102e3dad42bSJoel Becker * The following value pairs have special meanings to dlmglue, thus 103e3dad42bSJoel Becker * the right hand side needs to stay unique - never duplicate the 104e3dad42bSJoel Becker * mapping elsewhere in the table! 105e3dad42bSJoel Becker * 106e3dad42bSJoel Becker * DLM_NORMAL: 0 107e3dad42bSJoel Becker * DLM_NOTQUEUED: -EAGAIN 108e3dad42bSJoel Becker * DLM_CANCELGRANT: -EBUSY 109e3dad42bSJoel Becker * DLM_CANCEL: -DLM_ECANCEL 110e3dad42bSJoel Becker */ 111e3dad42bSJoel Becker /* Keep in sync with dlmapi.h */ 112e3dad42bSJoel Becker static int status_map[] = { 113e3dad42bSJoel Becker [DLM_NORMAL] = 0, /* Success */ 114e3dad42bSJoel Becker [DLM_GRANTED] = -EINVAL, 115e3dad42bSJoel Becker [DLM_DENIED] = -EACCES, 116e3dad42bSJoel Becker [DLM_DENIED_NOLOCKS] = -EACCES, 117e3dad42bSJoel Becker [DLM_WORKING] = -EACCES, 118e3dad42bSJoel Becker [DLM_BLOCKED] = -EINVAL, 119e3dad42bSJoel Becker [DLM_BLOCKED_ORPHAN] = -EINVAL, 120e3dad42bSJoel Becker [DLM_DENIED_GRACE_PERIOD] = -EACCES, 121e3dad42bSJoel Becker [DLM_SYSERR] = -ENOMEM, /* It is what it is */ 122e3dad42bSJoel Becker [DLM_NOSUPPORT] = -EPROTO, 123e3dad42bSJoel Becker [DLM_CANCELGRANT] = -EBUSY, /* Cancel after grant */ 124e3dad42bSJoel Becker [DLM_IVLOCKID] = -EINVAL, 125e3dad42bSJoel Becker [DLM_SYNC] = -EINVAL, 126e3dad42bSJoel Becker [DLM_BADTYPE] = -EINVAL, 127e3dad42bSJoel Becker [DLM_BADRESOURCE] = -EINVAL, 128e3dad42bSJoel Becker [DLM_MAXHANDLES] = -ENOMEM, 129e3dad42bSJoel Becker [DLM_NOCLINFO] = -EINVAL, 130e3dad42bSJoel Becker [DLM_NOLOCKMGR] = -EINVAL, 131e3dad42bSJoel Becker [DLM_NOPURGED] = -EINVAL, 132e3dad42bSJoel Becker [DLM_BADARGS] = -EINVAL, 133e3dad42bSJoel Becker [DLM_VOID] = -EINVAL, 134e3dad42bSJoel Becker [DLM_NOTQUEUED] = -EAGAIN, /* Trylock failed */ 135e3dad42bSJoel Becker [DLM_IVBUFLEN] = -EINVAL, 136e3dad42bSJoel Becker [DLM_CVTUNGRANT] = -EPERM, 137e3dad42bSJoel Becker [DLM_BADPARAM] = -EINVAL, 138e3dad42bSJoel Becker [DLM_VALNOTVALID] = -EINVAL, 139e3dad42bSJoel Becker [DLM_REJECTED] = -EPERM, 140e3dad42bSJoel Becker [DLM_ABORT] = -EINVAL, 141e3dad42bSJoel Becker [DLM_CANCEL] = -DLM_ECANCEL, /* Successful cancel */ 142e3dad42bSJoel Becker [DLM_IVRESHANDLE] = -EINVAL, 143e3dad42bSJoel Becker [DLM_DEADLOCK] = -EDEADLK, 144e3dad42bSJoel Becker [DLM_DENIED_NOASTS] = -EINVAL, 145e3dad42bSJoel Becker [DLM_FORWARD] = -EINVAL, 146e3dad42bSJoel Becker [DLM_TIMEOUT] = -ETIMEDOUT, 147e3dad42bSJoel Becker [DLM_IVGROUPID] = -EINVAL, 148e3dad42bSJoel Becker [DLM_VERS_CONFLICT] = -EOPNOTSUPP, 149e3dad42bSJoel Becker [DLM_BAD_DEVICE_PATH] = -ENOENT, 150e3dad42bSJoel Becker [DLM_NO_DEVICE_PERMISSION] = -EPERM, 151e3dad42bSJoel Becker [DLM_NO_CONTROL_DEVICE] = -ENOENT, 152e3dad42bSJoel Becker [DLM_RECOVERING] = -ENOTCONN, 153e3dad42bSJoel Becker [DLM_MIGRATING] = -ERESTART, 154e3dad42bSJoel Becker [DLM_MAXSTATS] = -EINVAL, 155e3dad42bSJoel Becker }; 156e3dad42bSJoel Becker 157e3dad42bSJoel Becker static int dlm_status_to_errno(enum dlm_status status) 158e3dad42bSJoel Becker { 1598a57a9ddSRoel Kluin BUG_ON(status < 0 || status >= ARRAY_SIZE(status_map)); 160e3dad42bSJoel Becker 161e3dad42bSJoel Becker return status_map[status]; 162e3dad42bSJoel Becker } 163e3dad42bSJoel Becker 164e3dad42bSJoel Becker static void o2dlm_lock_ast_wrapper(void *astarg) 165e3dad42bSJoel Becker { 166c0e41338SJoel Becker struct ocfs2_dlm_lksb *lksb = astarg; 167a796d286SJoel Becker 168110946c8SJoel Becker lksb->lksb_conn->cc_proto->lp_lock_ast(lksb); 169e3dad42bSJoel Becker } 170e3dad42bSJoel Becker 171e3dad42bSJoel Becker static void o2dlm_blocking_ast_wrapper(void *astarg, int level) 172e3dad42bSJoel Becker { 173c0e41338SJoel Becker struct ocfs2_dlm_lksb *lksb = astarg; 174a796d286SJoel Becker 175110946c8SJoel Becker lksb->lksb_conn->cc_proto->lp_blocking_ast(lksb, level); 176e3dad42bSJoel Becker } 177e3dad42bSJoel Becker 178e3dad42bSJoel Becker static void o2dlm_unlock_ast_wrapper(void *astarg, enum dlm_status status) 179e3dad42bSJoel Becker { 180c0e41338SJoel Becker struct ocfs2_dlm_lksb *lksb = astarg; 181e3dad42bSJoel Becker int error = dlm_status_to_errno(status); 182e3dad42bSJoel Becker 183e3dad42bSJoel Becker /* 184e3dad42bSJoel Becker * In o2dlm, you can get both the lock_ast() for the lock being 185e3dad42bSJoel Becker * granted and the unlock_ast() for the CANCEL failing. A 186e3dad42bSJoel Becker * successful cancel sends DLM_NORMAL here. If the 187e3dad42bSJoel Becker * lock grant happened before the cancel arrived, you get 188e3dad42bSJoel Becker * DLM_CANCELGRANT. 189e3dad42bSJoel Becker * 190e3dad42bSJoel Becker * There's no need for the double-ast. If we see DLM_CANCELGRANT, 191e3dad42bSJoel Becker * we just ignore it. We expect the lock_ast() to handle the 192e3dad42bSJoel Becker * granted lock. 193e3dad42bSJoel Becker */ 194e3dad42bSJoel Becker if (status == DLM_CANCELGRANT) 195e3dad42bSJoel Becker return; 196e3dad42bSJoel Becker 197110946c8SJoel Becker lksb->lksb_conn->cc_proto->lp_unlock_ast(lksb, error); 198e3dad42bSJoel Becker } 199e3dad42bSJoel Becker 200e3dad42bSJoel Becker static int o2cb_dlm_lock(struct ocfs2_cluster_connection *conn, 201e3dad42bSJoel Becker int mode, 202c0e41338SJoel Becker struct ocfs2_dlm_lksb *lksb, 203e3dad42bSJoel Becker u32 flags, 204e3dad42bSJoel Becker void *name, 205a796d286SJoel Becker unsigned int namelen) 206e3dad42bSJoel Becker { 207e3dad42bSJoel Becker enum dlm_status status; 208e3dad42bSJoel Becker int o2dlm_mode = mode_to_o2dlm(mode); 209e3dad42bSJoel Becker int o2dlm_flags = flags_to_o2dlm(flags); 210e3dad42bSJoel Becker int ret; 211e3dad42bSJoel Becker 212e3dad42bSJoel Becker status = dlmlock(conn->cc_lockspace, o2dlm_mode, &lksb->lksb_o2dlm, 213e3dad42bSJoel Becker o2dlm_flags, name, namelen, 214a796d286SJoel Becker o2dlm_lock_ast_wrapper, lksb, 215e3dad42bSJoel Becker o2dlm_blocking_ast_wrapper); 216e3dad42bSJoel Becker ret = dlm_status_to_errno(status); 217e3dad42bSJoel Becker return ret; 218e3dad42bSJoel Becker } 219e3dad42bSJoel Becker 220e3dad42bSJoel Becker static int o2cb_dlm_unlock(struct ocfs2_cluster_connection *conn, 221c0e41338SJoel Becker struct ocfs2_dlm_lksb *lksb, 222a796d286SJoel Becker u32 flags) 223e3dad42bSJoel Becker { 224e3dad42bSJoel Becker enum dlm_status status; 225e3dad42bSJoel Becker int o2dlm_flags = flags_to_o2dlm(flags); 226e3dad42bSJoel Becker int ret; 227e3dad42bSJoel Becker 228e3dad42bSJoel Becker status = dlmunlock(conn->cc_lockspace, &lksb->lksb_o2dlm, 229a796d286SJoel Becker o2dlm_flags, o2dlm_unlock_ast_wrapper, lksb); 230e3dad42bSJoel Becker ret = dlm_status_to_errno(status); 231e3dad42bSJoel Becker return ret; 232e3dad42bSJoel Becker } 233e3dad42bSJoel Becker 234c0e41338SJoel Becker static int o2cb_dlm_lock_status(struct ocfs2_dlm_lksb *lksb) 235e3dad42bSJoel Becker { 236e3dad42bSJoel Becker return dlm_status_to_errno(lksb->lksb_o2dlm.status); 237e3dad42bSJoel Becker } 238e3dad42bSJoel Becker 2391c520dfbSJoel Becker /* 2401c520dfbSJoel Becker * o2dlm aways has a "valid" LVB. If the dlm loses track of the LVB 2411c520dfbSJoel Becker * contents, it will zero out the LVB. Thus the caller can always trust 2421c520dfbSJoel Becker * the contents. 2431c520dfbSJoel Becker */ 244c0e41338SJoel Becker static int o2cb_dlm_lvb_valid(struct ocfs2_dlm_lksb *lksb) 2451c520dfbSJoel Becker { 2461c520dfbSJoel Becker return 1; 2471c520dfbSJoel Becker } 2481c520dfbSJoel Becker 249c0e41338SJoel Becker static void *o2cb_dlm_lvb(struct ocfs2_dlm_lksb *lksb) 250e3dad42bSJoel Becker { 251e3dad42bSJoel Becker return (void *)(lksb->lksb_o2dlm.lvb); 252e3dad42bSJoel Becker } 253e3dad42bSJoel Becker 254c0e41338SJoel Becker static void o2cb_dump_lksb(struct ocfs2_dlm_lksb *lksb) 255e3dad42bSJoel Becker { 256e3dad42bSJoel Becker dlm_print_one_lock(lksb->lksb_o2dlm.lockid); 257e3dad42bSJoel Becker } 258e3dad42bSJoel Becker 259e3dad42bSJoel Becker /* 2606b27f62fSSunil Mushran * Check if this node is heartbeating and is connected to all other 2616b27f62fSSunil Mushran * heartbeating nodes. 2626b27f62fSSunil Mushran */ 2636b27f62fSSunil Mushran static int o2cb_cluster_check(void) 2646b27f62fSSunil Mushran { 2656b27f62fSSunil Mushran u8 node_num; 2666b27f62fSSunil Mushran int i; 2676b27f62fSSunil Mushran unsigned long hbmap[BITS_TO_LONGS(O2NM_MAX_NODES)]; 2686b27f62fSSunil Mushran unsigned long netmap[BITS_TO_LONGS(O2NM_MAX_NODES)]; 2696b27f62fSSunil Mushran 2706b27f62fSSunil Mushran node_num = o2nm_this_node(); 2716b27f62fSSunil Mushran if (node_num == O2NM_MAX_NODES) { 2726b27f62fSSunil Mushran printk(KERN_ERR "o2cb: This node has not been configured.\n"); 2736b27f62fSSunil Mushran return -EINVAL; 2746b27f62fSSunil Mushran } 2756b27f62fSSunil Mushran 2766b27f62fSSunil Mushran /* 2776b27f62fSSunil Mushran * o2dlm expects o2net sockets to be created. If not, then 2786b27f62fSSunil Mushran * dlm_join_domain() fails with a stack of errors which are both cryptic 2796b27f62fSSunil Mushran * and incomplete. The idea here is to detect upfront whether we have 2806b27f62fSSunil Mushran * managed to connect to all nodes or not. If not, then list the nodes 2816b27f62fSSunil Mushran * to allow the user to check the configuration (incorrect IP, firewall, 2826b27f62fSSunil Mushran * etc.) Yes, this is racy. But its not the end of the world. 2836b27f62fSSunil Mushran */ 2846b27f62fSSunil Mushran #define O2CB_MAP_STABILIZE_COUNT 60 2856b27f62fSSunil Mushran for (i = 0; i < O2CB_MAP_STABILIZE_COUNT; ++i) { 2866b27f62fSSunil Mushran o2hb_fill_node_map(hbmap, sizeof(hbmap)); 2876b27f62fSSunil Mushran if (!test_bit(node_num, hbmap)) { 2886b27f62fSSunil Mushran printk(KERN_ERR "o2cb: %s heartbeat has not been " 2896b27f62fSSunil Mushran "started.\n", (o2hb_global_heartbeat_active() ? 2906b27f62fSSunil Mushran "Global" : "Local")); 2916b27f62fSSunil Mushran return -EINVAL; 2926b27f62fSSunil Mushran } 2936b27f62fSSunil Mushran o2net_fill_node_map(netmap, sizeof(netmap)); 2946b27f62fSSunil Mushran /* Force set the current node to allow easy compare */ 2956b27f62fSSunil Mushran set_bit(node_num, netmap); 2966b27f62fSSunil Mushran if (!memcmp(hbmap, netmap, sizeof(hbmap))) 2976b27f62fSSunil Mushran return 0; 2986b27f62fSSunil Mushran if (i < O2CB_MAP_STABILIZE_COUNT) 2996b27f62fSSunil Mushran msleep(1000); 3006b27f62fSSunil Mushran } 3016b27f62fSSunil Mushran 3026b27f62fSSunil Mushran printk(KERN_ERR "o2cb: This node could not connect to nodes:"); 3036b27f62fSSunil Mushran i = -1; 3046b27f62fSSunil Mushran while ((i = find_next_bit(hbmap, O2NM_MAX_NODES, 3056b27f62fSSunil Mushran i + 1)) < O2NM_MAX_NODES) { 3066b27f62fSSunil Mushran if (!test_bit(i, netmap)) 3076b27f62fSSunil Mushran printk(" %u", i); 3086b27f62fSSunil Mushran } 3096b27f62fSSunil Mushran printk(".\n"); 3106b27f62fSSunil Mushran 3116b27f62fSSunil Mushran return -ENOTCONN; 3126b27f62fSSunil Mushran } 3136b27f62fSSunil Mushran 3146b27f62fSSunil Mushran /* 315e3dad42bSJoel Becker * Called from the dlm when it's about to evict a node. This is how the 316e3dad42bSJoel Becker * classic stack signals node death. 317e3dad42bSJoel Becker */ 318e3dad42bSJoel Becker static void o2dlm_eviction_cb(int node_num, void *data) 319e3dad42bSJoel Becker { 320e3dad42bSJoel Becker struct ocfs2_cluster_connection *conn = data; 321e3dad42bSJoel Becker 322394eb3d3SSunil Mushran printk(KERN_NOTICE "o2cb: o2dlm has evicted node %d from domain %.*s\n", 323e3dad42bSJoel Becker node_num, conn->cc_namelen, conn->cc_name); 324e3dad42bSJoel Becker 325e3dad42bSJoel Becker conn->cc_recovery_handler(node_num, conn->cc_recovery_data); 326e3dad42bSJoel Becker } 327e3dad42bSJoel Becker 328e3dad42bSJoel Becker static int o2cb_cluster_connect(struct ocfs2_cluster_connection *conn) 329e3dad42bSJoel Becker { 330e3dad42bSJoel Becker int rc = 0; 331e3dad42bSJoel Becker u32 dlm_key; 332e3dad42bSJoel Becker struct dlm_ctxt *dlm; 333e3dad42bSJoel Becker struct o2dlm_private *priv; 334e5f2cb2bSWengang Wang struct dlm_protocol_version fs_version; 335e3dad42bSJoel Becker 336e3dad42bSJoel Becker BUG_ON(conn == NULL); 337110946c8SJoel Becker BUG_ON(conn->cc_proto == NULL); 338e3dad42bSJoel Becker 3396b27f62fSSunil Mushran /* Ensure cluster stack is up and all nodes are connected */ 3406b27f62fSSunil Mushran rc = o2cb_cluster_check(); 3416b27f62fSSunil Mushran if (rc) { 3426b27f62fSSunil Mushran printk(KERN_ERR "o2cb: Cluster check failed. Fix errors " 3436b27f62fSSunil Mushran "before retrying.\n"); 344e3dad42bSJoel Becker goto out; 345e3dad42bSJoel Becker } 346e3dad42bSJoel Becker 347e3dad42bSJoel Becker priv = kzalloc(sizeof(struct o2dlm_private), GFP_KERNEL); 348e3dad42bSJoel Becker if (!priv) { 349e3dad42bSJoel Becker rc = -ENOMEM; 350e3dad42bSJoel Becker goto out_free; 351e3dad42bSJoel Becker } 352e3dad42bSJoel Becker 353e3dad42bSJoel Becker /* This just fills the structure in. It is safe to pass conn. */ 354e3dad42bSJoel Becker dlm_setup_eviction_cb(&priv->op_eviction_cb, o2dlm_eviction_cb, 355e3dad42bSJoel Becker conn); 356e3dad42bSJoel Becker 357e3dad42bSJoel Becker conn->cc_private = priv; 358e3dad42bSJoel Becker 359e3dad42bSJoel Becker /* used by the dlm code to make message headers unique, each 360e3dad42bSJoel Becker * node in this domain must agree on this. */ 361e3dad42bSJoel Becker dlm_key = crc32_le(0, conn->cc_name, conn->cc_namelen); 362e5f2cb2bSWengang Wang fs_version.pv_major = conn->cc_version.pv_major; 363e5f2cb2bSWengang Wang fs_version.pv_minor = conn->cc_version.pv_minor; 364e3dad42bSJoel Becker 365e5f2cb2bSWengang Wang dlm = dlm_register_domain(conn->cc_name, dlm_key, &fs_version); 366e3dad42bSJoel Becker if (IS_ERR(dlm)) { 367e3dad42bSJoel Becker rc = PTR_ERR(dlm); 368e3dad42bSJoel Becker mlog_errno(rc); 369e3dad42bSJoel Becker goto out_free; 370e3dad42bSJoel Becker } 371e3dad42bSJoel Becker 372e5f2cb2bSWengang Wang conn->cc_version.pv_major = fs_version.pv_major; 373e5f2cb2bSWengang Wang conn->cc_version.pv_minor = fs_version.pv_minor; 374e3dad42bSJoel Becker conn->cc_lockspace = dlm; 375e3dad42bSJoel Becker 376e3dad42bSJoel Becker dlm_register_eviction_cb(dlm, &priv->op_eviction_cb); 377e3dad42bSJoel Becker 378e3dad42bSJoel Becker out_free: 379*d787ab09STim Gardner if (rc) 380e3dad42bSJoel Becker kfree(conn->cc_private); 381e3dad42bSJoel Becker 382e3dad42bSJoel Becker out: 383e3dad42bSJoel Becker return rc; 384e3dad42bSJoel Becker } 385e3dad42bSJoel Becker 3862c39450bSJoel Becker static int o2cb_cluster_disconnect(struct ocfs2_cluster_connection *conn) 387e3dad42bSJoel Becker { 388e3dad42bSJoel Becker struct dlm_ctxt *dlm = conn->cc_lockspace; 389e3dad42bSJoel Becker struct o2dlm_private *priv = conn->cc_private; 390e3dad42bSJoel Becker 391e3dad42bSJoel Becker dlm_unregister_eviction_cb(&priv->op_eviction_cb); 392e3dad42bSJoel Becker conn->cc_private = NULL; 393e3dad42bSJoel Becker kfree(priv); 394e3dad42bSJoel Becker 395e3dad42bSJoel Becker dlm_unregister_domain(dlm); 396e3dad42bSJoel Becker conn->cc_lockspace = NULL; 397e3dad42bSJoel Becker 398e3dad42bSJoel Becker return 0; 399e3dad42bSJoel Becker } 400e3dad42bSJoel Becker 401e3dad42bSJoel Becker static int o2cb_cluster_this_node(unsigned int *node) 402e3dad42bSJoel Becker { 403e3dad42bSJoel Becker int node_num; 404e3dad42bSJoel Becker 405e3dad42bSJoel Becker node_num = o2nm_this_node(); 406e3dad42bSJoel Becker if (node_num == O2NM_INVALID_NODE_NUM) 407e3dad42bSJoel Becker return -ENOENT; 408e3dad42bSJoel Becker 409e3dad42bSJoel Becker if (node_num >= O2NM_MAX_NODES) 410e3dad42bSJoel Becker return -EOVERFLOW; 411e3dad42bSJoel Becker 412e3dad42bSJoel Becker *node = node_num; 413e3dad42bSJoel Becker return 0; 414e3dad42bSJoel Becker } 415e3dad42bSJoel Becker 4164af694e6SAdrian Bunk static struct ocfs2_stack_operations o2cb_stack_ops = { 417e3dad42bSJoel Becker .connect = o2cb_cluster_connect, 418e3dad42bSJoel Becker .disconnect = o2cb_cluster_disconnect, 419e3dad42bSJoel Becker .this_node = o2cb_cluster_this_node, 420e3dad42bSJoel Becker .dlm_lock = o2cb_dlm_lock, 421e3dad42bSJoel Becker .dlm_unlock = o2cb_dlm_unlock, 422e3dad42bSJoel Becker .lock_status = o2cb_dlm_lock_status, 4231c520dfbSJoel Becker .lvb_valid = o2cb_dlm_lvb_valid, 424e3dad42bSJoel Becker .lock_lvb = o2cb_dlm_lvb, 425e3dad42bSJoel Becker .dump_lksb = o2cb_dump_lksb, 426e3dad42bSJoel Becker }; 427e3dad42bSJoel Becker 428286eaa95SJoel Becker static struct ocfs2_stack_plugin o2cb_stack = { 429286eaa95SJoel Becker .sp_name = "o2cb", 430286eaa95SJoel Becker .sp_ops = &o2cb_stack_ops, 431286eaa95SJoel Becker .sp_owner = THIS_MODULE, 432286eaa95SJoel Becker }; 433286eaa95SJoel Becker 434286eaa95SJoel Becker static int __init o2cb_stack_init(void) 435286eaa95SJoel Becker { 436286eaa95SJoel Becker return ocfs2_stack_glue_register(&o2cb_stack); 437286eaa95SJoel Becker } 438286eaa95SJoel Becker 439286eaa95SJoel Becker static void __exit o2cb_stack_exit(void) 440286eaa95SJoel Becker { 441286eaa95SJoel Becker ocfs2_stack_glue_unregister(&o2cb_stack); 442286eaa95SJoel Becker } 443286eaa95SJoel Becker 444286eaa95SJoel Becker MODULE_AUTHOR("Oracle"); 445286eaa95SJoel Becker MODULE_DESCRIPTION("ocfs2 driver for the classic o2cb stack"); 446286eaa95SJoel Becker MODULE_LICENSE("GPL"); 447286eaa95SJoel Becker module_init(o2cb_stack_init); 448286eaa95SJoel Becker module_exit(o2cb_stack_exit); 449