18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 28c2ecf20Sopenharmony_ci/* -*- mode: c; c-basic-offset: 8; -*- 38c2ecf20Sopenharmony_ci * vim: noexpandtab sw=8 ts=8 sts=0: 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * dlmast.c 68c2ecf20Sopenharmony_ci * 78c2ecf20Sopenharmony_ci * AST and BAST functionality for local and remote nodes 88c2ecf20Sopenharmony_ci * 98c2ecf20Sopenharmony_ci * Copyright (C) 2004 Oracle. All rights reserved. 108c2ecf20Sopenharmony_ci */ 118c2ecf20Sopenharmony_ci 128c2ecf20Sopenharmony_ci 138c2ecf20Sopenharmony_ci#include <linux/module.h> 148c2ecf20Sopenharmony_ci#include <linux/fs.h> 158c2ecf20Sopenharmony_ci#include <linux/types.h> 168c2ecf20Sopenharmony_ci#include <linux/highmem.h> 178c2ecf20Sopenharmony_ci#include <linux/init.h> 188c2ecf20Sopenharmony_ci#include <linux/sysctl.h> 198c2ecf20Sopenharmony_ci#include <linux/random.h> 208c2ecf20Sopenharmony_ci#include <linux/blkdev.h> 218c2ecf20Sopenharmony_ci#include <linux/socket.h> 228c2ecf20Sopenharmony_ci#include <linux/inet.h> 238c2ecf20Sopenharmony_ci#include <linux/spinlock.h> 248c2ecf20Sopenharmony_ci 258c2ecf20Sopenharmony_ci 268c2ecf20Sopenharmony_ci#include "../cluster/heartbeat.h" 278c2ecf20Sopenharmony_ci#include "../cluster/nodemanager.h" 288c2ecf20Sopenharmony_ci#include "../cluster/tcp.h" 298c2ecf20Sopenharmony_ci 308c2ecf20Sopenharmony_ci#include "dlmapi.h" 318c2ecf20Sopenharmony_ci#include "dlmcommon.h" 328c2ecf20Sopenharmony_ci 338c2ecf20Sopenharmony_ci#define MLOG_MASK_PREFIX ML_DLM 348c2ecf20Sopenharmony_ci#include "../cluster/masklog.h" 358c2ecf20Sopenharmony_ci 368c2ecf20Sopenharmony_cistatic void dlm_update_lvb(struct dlm_ctxt *dlm, struct dlm_lock_resource *res, 378c2ecf20Sopenharmony_ci struct dlm_lock *lock); 388c2ecf20Sopenharmony_cistatic int dlm_should_cancel_bast(struct dlm_ctxt *dlm, struct dlm_lock *lock); 398c2ecf20Sopenharmony_ci 408c2ecf20Sopenharmony_ci/* Should be called as an ast gets queued to see if the new 418c2ecf20Sopenharmony_ci * lock level will obsolete a pending bast. 428c2ecf20Sopenharmony_ci * For example, if dlm_thread queued a bast for an EX lock that 438c2ecf20Sopenharmony_ci * was blocking another EX, but before sending the bast the 448c2ecf20Sopenharmony_ci * lock owner downconverted to NL, the bast is now obsolete. 458c2ecf20Sopenharmony_ci * Only the ast should be sent. 468c2ecf20Sopenharmony_ci * This is needed because the lock and convert paths can queue 478c2ecf20Sopenharmony_ci * asts out-of-band (not waiting for dlm_thread) in order to 488c2ecf20Sopenharmony_ci * allow for LKM_NOQUEUE to get immediate responses. */ 498c2ecf20Sopenharmony_cistatic int dlm_should_cancel_bast(struct dlm_ctxt *dlm, struct dlm_lock *lock) 508c2ecf20Sopenharmony_ci{ 518c2ecf20Sopenharmony_ci assert_spin_locked(&dlm->ast_lock); 528c2ecf20Sopenharmony_ci assert_spin_locked(&lock->spinlock); 538c2ecf20Sopenharmony_ci 548c2ecf20Sopenharmony_ci if (lock->ml.highest_blocked == LKM_IVMODE) 558c2ecf20Sopenharmony_ci return 0; 568c2ecf20Sopenharmony_ci BUG_ON(lock->ml.highest_blocked == LKM_NLMODE); 578c2ecf20Sopenharmony_ci 588c2ecf20Sopenharmony_ci if (lock->bast_pending && 598c2ecf20Sopenharmony_ci list_empty(&lock->bast_list)) 608c2ecf20Sopenharmony_ci /* old bast already sent, ok */ 618c2ecf20Sopenharmony_ci return 0; 628c2ecf20Sopenharmony_ci 638c2ecf20Sopenharmony_ci if (lock->ml.type == LKM_EXMODE) 648c2ecf20Sopenharmony_ci /* EX blocks anything left, any bast still valid */ 658c2ecf20Sopenharmony_ci return 0; 668c2ecf20Sopenharmony_ci else if (lock->ml.type == LKM_NLMODE) 678c2ecf20Sopenharmony_ci /* NL blocks nothing, no reason to send any bast, cancel it */ 688c2ecf20Sopenharmony_ci return 1; 698c2ecf20Sopenharmony_ci else if (lock->ml.highest_blocked != LKM_EXMODE) 708c2ecf20Sopenharmony_ci /* PR only blocks EX */ 718c2ecf20Sopenharmony_ci return 1; 728c2ecf20Sopenharmony_ci 738c2ecf20Sopenharmony_ci return 0; 748c2ecf20Sopenharmony_ci} 758c2ecf20Sopenharmony_ci 768c2ecf20Sopenharmony_civoid __dlm_queue_ast(struct dlm_ctxt *dlm, struct dlm_lock *lock) 778c2ecf20Sopenharmony_ci{ 788c2ecf20Sopenharmony_ci struct dlm_lock_resource *res; 798c2ecf20Sopenharmony_ci 808c2ecf20Sopenharmony_ci BUG_ON(!dlm); 818c2ecf20Sopenharmony_ci BUG_ON(!lock); 828c2ecf20Sopenharmony_ci 838c2ecf20Sopenharmony_ci res = lock->lockres; 848c2ecf20Sopenharmony_ci 858c2ecf20Sopenharmony_ci assert_spin_locked(&dlm->ast_lock); 868c2ecf20Sopenharmony_ci 878c2ecf20Sopenharmony_ci if (!list_empty(&lock->ast_list)) { 888c2ecf20Sopenharmony_ci mlog(ML_ERROR, "%s: res %.*s, lock %u:%llu, " 898c2ecf20Sopenharmony_ci "AST list not empty, pending %d, newlevel %d\n", 908c2ecf20Sopenharmony_ci dlm->name, res->lockname.len, res->lockname.name, 918c2ecf20Sopenharmony_ci dlm_get_lock_cookie_node(be64_to_cpu(lock->ml.cookie)), 928c2ecf20Sopenharmony_ci dlm_get_lock_cookie_seq(be64_to_cpu(lock->ml.cookie)), 938c2ecf20Sopenharmony_ci lock->ast_pending, lock->ml.type); 948c2ecf20Sopenharmony_ci BUG(); 958c2ecf20Sopenharmony_ci } 968c2ecf20Sopenharmony_ci if (lock->ast_pending) 978c2ecf20Sopenharmony_ci mlog(0, "%s: res %.*s, lock %u:%llu, AST getting flushed\n", 988c2ecf20Sopenharmony_ci dlm->name, res->lockname.len, res->lockname.name, 998c2ecf20Sopenharmony_ci dlm_get_lock_cookie_node(be64_to_cpu(lock->ml.cookie)), 1008c2ecf20Sopenharmony_ci dlm_get_lock_cookie_seq(be64_to_cpu(lock->ml.cookie))); 1018c2ecf20Sopenharmony_ci 1028c2ecf20Sopenharmony_ci /* putting lock on list, add a ref */ 1038c2ecf20Sopenharmony_ci dlm_lock_get(lock); 1048c2ecf20Sopenharmony_ci spin_lock(&lock->spinlock); 1058c2ecf20Sopenharmony_ci 1068c2ecf20Sopenharmony_ci /* check to see if this ast obsoletes the bast */ 1078c2ecf20Sopenharmony_ci if (dlm_should_cancel_bast(dlm, lock)) { 1088c2ecf20Sopenharmony_ci mlog(0, "%s: res %.*s, lock %u:%llu, Cancelling BAST\n", 1098c2ecf20Sopenharmony_ci dlm->name, res->lockname.len, res->lockname.name, 1108c2ecf20Sopenharmony_ci dlm_get_lock_cookie_node(be64_to_cpu(lock->ml.cookie)), 1118c2ecf20Sopenharmony_ci dlm_get_lock_cookie_seq(be64_to_cpu(lock->ml.cookie))); 1128c2ecf20Sopenharmony_ci lock->bast_pending = 0; 1138c2ecf20Sopenharmony_ci list_del_init(&lock->bast_list); 1148c2ecf20Sopenharmony_ci lock->ml.highest_blocked = LKM_IVMODE; 1158c2ecf20Sopenharmony_ci /* removing lock from list, remove a ref. guaranteed 1168c2ecf20Sopenharmony_ci * this won't be the last ref because of the get above, 1178c2ecf20Sopenharmony_ci * so res->spinlock will not be taken here */ 1188c2ecf20Sopenharmony_ci dlm_lock_put(lock); 1198c2ecf20Sopenharmony_ci /* free up the reserved bast that we are cancelling. 1208c2ecf20Sopenharmony_ci * guaranteed that this will not be the last reserved 1218c2ecf20Sopenharmony_ci * ast because *both* an ast and a bast were reserved 1228c2ecf20Sopenharmony_ci * to get to this point. the res->spinlock will not be 1238c2ecf20Sopenharmony_ci * taken here */ 1248c2ecf20Sopenharmony_ci dlm_lockres_release_ast(dlm, res); 1258c2ecf20Sopenharmony_ci } 1268c2ecf20Sopenharmony_ci list_add_tail(&lock->ast_list, &dlm->pending_asts); 1278c2ecf20Sopenharmony_ci lock->ast_pending = 1; 1288c2ecf20Sopenharmony_ci spin_unlock(&lock->spinlock); 1298c2ecf20Sopenharmony_ci} 1308c2ecf20Sopenharmony_ci 1318c2ecf20Sopenharmony_civoid dlm_queue_ast(struct dlm_ctxt *dlm, struct dlm_lock *lock) 1328c2ecf20Sopenharmony_ci{ 1338c2ecf20Sopenharmony_ci BUG_ON(!dlm); 1348c2ecf20Sopenharmony_ci BUG_ON(!lock); 1358c2ecf20Sopenharmony_ci 1368c2ecf20Sopenharmony_ci spin_lock(&dlm->ast_lock); 1378c2ecf20Sopenharmony_ci __dlm_queue_ast(dlm, lock); 1388c2ecf20Sopenharmony_ci spin_unlock(&dlm->ast_lock); 1398c2ecf20Sopenharmony_ci} 1408c2ecf20Sopenharmony_ci 1418c2ecf20Sopenharmony_ci 1428c2ecf20Sopenharmony_civoid __dlm_queue_bast(struct dlm_ctxt *dlm, struct dlm_lock *lock) 1438c2ecf20Sopenharmony_ci{ 1448c2ecf20Sopenharmony_ci struct dlm_lock_resource *res; 1458c2ecf20Sopenharmony_ci 1468c2ecf20Sopenharmony_ci BUG_ON(!dlm); 1478c2ecf20Sopenharmony_ci BUG_ON(!lock); 1488c2ecf20Sopenharmony_ci 1498c2ecf20Sopenharmony_ci assert_spin_locked(&dlm->ast_lock); 1508c2ecf20Sopenharmony_ci 1518c2ecf20Sopenharmony_ci res = lock->lockres; 1528c2ecf20Sopenharmony_ci 1538c2ecf20Sopenharmony_ci BUG_ON(!list_empty(&lock->bast_list)); 1548c2ecf20Sopenharmony_ci if (lock->bast_pending) 1558c2ecf20Sopenharmony_ci mlog(0, "%s: res %.*s, lock %u:%llu, BAST getting flushed\n", 1568c2ecf20Sopenharmony_ci dlm->name, res->lockname.len, res->lockname.name, 1578c2ecf20Sopenharmony_ci dlm_get_lock_cookie_node(be64_to_cpu(lock->ml.cookie)), 1588c2ecf20Sopenharmony_ci dlm_get_lock_cookie_seq(be64_to_cpu(lock->ml.cookie))); 1598c2ecf20Sopenharmony_ci 1608c2ecf20Sopenharmony_ci /* putting lock on list, add a ref */ 1618c2ecf20Sopenharmony_ci dlm_lock_get(lock); 1628c2ecf20Sopenharmony_ci spin_lock(&lock->spinlock); 1638c2ecf20Sopenharmony_ci list_add_tail(&lock->bast_list, &dlm->pending_basts); 1648c2ecf20Sopenharmony_ci lock->bast_pending = 1; 1658c2ecf20Sopenharmony_ci spin_unlock(&lock->spinlock); 1668c2ecf20Sopenharmony_ci} 1678c2ecf20Sopenharmony_ci 1688c2ecf20Sopenharmony_civoid dlm_queue_bast(struct dlm_ctxt *dlm, struct dlm_lock *lock) 1698c2ecf20Sopenharmony_ci{ 1708c2ecf20Sopenharmony_ci BUG_ON(!dlm); 1718c2ecf20Sopenharmony_ci BUG_ON(!lock); 1728c2ecf20Sopenharmony_ci 1738c2ecf20Sopenharmony_ci spin_lock(&dlm->ast_lock); 1748c2ecf20Sopenharmony_ci __dlm_queue_bast(dlm, lock); 1758c2ecf20Sopenharmony_ci spin_unlock(&dlm->ast_lock); 1768c2ecf20Sopenharmony_ci} 1778c2ecf20Sopenharmony_ci 1788c2ecf20Sopenharmony_cistatic void dlm_update_lvb(struct dlm_ctxt *dlm, struct dlm_lock_resource *res, 1798c2ecf20Sopenharmony_ci struct dlm_lock *lock) 1808c2ecf20Sopenharmony_ci{ 1818c2ecf20Sopenharmony_ci struct dlm_lockstatus *lksb = lock->lksb; 1828c2ecf20Sopenharmony_ci BUG_ON(!lksb); 1838c2ecf20Sopenharmony_ci 1848c2ecf20Sopenharmony_ci /* only updates if this node masters the lockres */ 1858c2ecf20Sopenharmony_ci spin_lock(&res->spinlock); 1868c2ecf20Sopenharmony_ci if (res->owner == dlm->node_num) { 1878c2ecf20Sopenharmony_ci /* check the lksb flags for the direction */ 1888c2ecf20Sopenharmony_ci if (lksb->flags & DLM_LKSB_GET_LVB) { 1898c2ecf20Sopenharmony_ci mlog(0, "getting lvb from lockres for %s node\n", 1908c2ecf20Sopenharmony_ci lock->ml.node == dlm->node_num ? "master" : 1918c2ecf20Sopenharmony_ci "remote"); 1928c2ecf20Sopenharmony_ci memcpy(lksb->lvb, res->lvb, DLM_LVB_LEN); 1938c2ecf20Sopenharmony_ci } 1948c2ecf20Sopenharmony_ci /* Do nothing for lvb put requests - they should be done in 1958c2ecf20Sopenharmony_ci * place when the lock is downconverted - otherwise we risk 1968c2ecf20Sopenharmony_ci * racing gets and puts which could result in old lvb data 1978c2ecf20Sopenharmony_ci * being propagated. We leave the put flag set and clear it 1988c2ecf20Sopenharmony_ci * here. In the future we might want to clear it at the time 1998c2ecf20Sopenharmony_ci * the put is actually done. 2008c2ecf20Sopenharmony_ci */ 2018c2ecf20Sopenharmony_ci } 2028c2ecf20Sopenharmony_ci spin_unlock(&res->spinlock); 2038c2ecf20Sopenharmony_ci 2048c2ecf20Sopenharmony_ci /* reset any lvb flags on the lksb */ 2058c2ecf20Sopenharmony_ci lksb->flags &= ~(DLM_LKSB_PUT_LVB|DLM_LKSB_GET_LVB); 2068c2ecf20Sopenharmony_ci} 2078c2ecf20Sopenharmony_ci 2088c2ecf20Sopenharmony_civoid dlm_do_local_ast(struct dlm_ctxt *dlm, struct dlm_lock_resource *res, 2098c2ecf20Sopenharmony_ci struct dlm_lock *lock) 2108c2ecf20Sopenharmony_ci{ 2118c2ecf20Sopenharmony_ci dlm_astlockfunc_t *fn; 2128c2ecf20Sopenharmony_ci 2138c2ecf20Sopenharmony_ci mlog(0, "%s: res %.*s, lock %u:%llu, Local AST\n", dlm->name, 2148c2ecf20Sopenharmony_ci res->lockname.len, res->lockname.name, 2158c2ecf20Sopenharmony_ci dlm_get_lock_cookie_node(be64_to_cpu(lock->ml.cookie)), 2168c2ecf20Sopenharmony_ci dlm_get_lock_cookie_seq(be64_to_cpu(lock->ml.cookie))); 2178c2ecf20Sopenharmony_ci 2188c2ecf20Sopenharmony_ci fn = lock->ast; 2198c2ecf20Sopenharmony_ci BUG_ON(lock->ml.node != dlm->node_num); 2208c2ecf20Sopenharmony_ci 2218c2ecf20Sopenharmony_ci dlm_update_lvb(dlm, res, lock); 2228c2ecf20Sopenharmony_ci (*fn)(lock->astdata); 2238c2ecf20Sopenharmony_ci} 2248c2ecf20Sopenharmony_ci 2258c2ecf20Sopenharmony_ci 2268c2ecf20Sopenharmony_ciint dlm_do_remote_ast(struct dlm_ctxt *dlm, struct dlm_lock_resource *res, 2278c2ecf20Sopenharmony_ci struct dlm_lock *lock) 2288c2ecf20Sopenharmony_ci{ 2298c2ecf20Sopenharmony_ci int ret; 2308c2ecf20Sopenharmony_ci struct dlm_lockstatus *lksb; 2318c2ecf20Sopenharmony_ci int lksbflags; 2328c2ecf20Sopenharmony_ci 2338c2ecf20Sopenharmony_ci mlog(0, "%s: res %.*s, lock %u:%llu, Remote AST\n", dlm->name, 2348c2ecf20Sopenharmony_ci res->lockname.len, res->lockname.name, 2358c2ecf20Sopenharmony_ci dlm_get_lock_cookie_node(be64_to_cpu(lock->ml.cookie)), 2368c2ecf20Sopenharmony_ci dlm_get_lock_cookie_seq(be64_to_cpu(lock->ml.cookie))); 2378c2ecf20Sopenharmony_ci 2388c2ecf20Sopenharmony_ci lksb = lock->lksb; 2398c2ecf20Sopenharmony_ci BUG_ON(lock->ml.node == dlm->node_num); 2408c2ecf20Sopenharmony_ci 2418c2ecf20Sopenharmony_ci lksbflags = lksb->flags; 2428c2ecf20Sopenharmony_ci dlm_update_lvb(dlm, res, lock); 2438c2ecf20Sopenharmony_ci 2448c2ecf20Sopenharmony_ci /* lock request came from another node 2458c2ecf20Sopenharmony_ci * go do the ast over there */ 2468c2ecf20Sopenharmony_ci ret = dlm_send_proxy_ast(dlm, res, lock, lksbflags); 2478c2ecf20Sopenharmony_ci return ret; 2488c2ecf20Sopenharmony_ci} 2498c2ecf20Sopenharmony_ci 2508c2ecf20Sopenharmony_civoid dlm_do_local_bast(struct dlm_ctxt *dlm, struct dlm_lock_resource *res, 2518c2ecf20Sopenharmony_ci struct dlm_lock *lock, int blocked_type) 2528c2ecf20Sopenharmony_ci{ 2538c2ecf20Sopenharmony_ci dlm_bastlockfunc_t *fn = lock->bast; 2548c2ecf20Sopenharmony_ci 2558c2ecf20Sopenharmony_ci BUG_ON(lock->ml.node != dlm->node_num); 2568c2ecf20Sopenharmony_ci 2578c2ecf20Sopenharmony_ci mlog(0, "%s: res %.*s, lock %u:%llu, Local BAST, blocked %d\n", 2588c2ecf20Sopenharmony_ci dlm->name, res->lockname.len, res->lockname.name, 2598c2ecf20Sopenharmony_ci dlm_get_lock_cookie_node(be64_to_cpu(lock->ml.cookie)), 2608c2ecf20Sopenharmony_ci dlm_get_lock_cookie_seq(be64_to_cpu(lock->ml.cookie)), 2618c2ecf20Sopenharmony_ci blocked_type); 2628c2ecf20Sopenharmony_ci 2638c2ecf20Sopenharmony_ci (*fn)(lock->astdata, blocked_type); 2648c2ecf20Sopenharmony_ci} 2658c2ecf20Sopenharmony_ci 2668c2ecf20Sopenharmony_ci 2678c2ecf20Sopenharmony_ci 2688c2ecf20Sopenharmony_ciint dlm_proxy_ast_handler(struct o2net_msg *msg, u32 len, void *data, 2698c2ecf20Sopenharmony_ci void **ret_data) 2708c2ecf20Sopenharmony_ci{ 2718c2ecf20Sopenharmony_ci int ret; 2728c2ecf20Sopenharmony_ci unsigned int locklen; 2738c2ecf20Sopenharmony_ci struct dlm_ctxt *dlm = data; 2748c2ecf20Sopenharmony_ci struct dlm_lock_resource *res = NULL; 2758c2ecf20Sopenharmony_ci struct dlm_lock *lock = NULL; 2768c2ecf20Sopenharmony_ci struct dlm_proxy_ast *past = (struct dlm_proxy_ast *) msg->buf; 2778c2ecf20Sopenharmony_ci char *name; 2788c2ecf20Sopenharmony_ci struct list_head *head = NULL; 2798c2ecf20Sopenharmony_ci __be64 cookie; 2808c2ecf20Sopenharmony_ci u32 flags; 2818c2ecf20Sopenharmony_ci u8 node; 2828c2ecf20Sopenharmony_ci 2838c2ecf20Sopenharmony_ci if (!dlm_grab(dlm)) { 2848c2ecf20Sopenharmony_ci dlm_error(DLM_REJECTED); 2858c2ecf20Sopenharmony_ci return DLM_REJECTED; 2868c2ecf20Sopenharmony_ci } 2878c2ecf20Sopenharmony_ci 2888c2ecf20Sopenharmony_ci mlog_bug_on_msg(!dlm_domain_fully_joined(dlm), 2898c2ecf20Sopenharmony_ci "Domain %s not fully joined!\n", dlm->name); 2908c2ecf20Sopenharmony_ci 2918c2ecf20Sopenharmony_ci name = past->name; 2928c2ecf20Sopenharmony_ci locklen = past->namelen; 2938c2ecf20Sopenharmony_ci cookie = past->cookie; 2948c2ecf20Sopenharmony_ci flags = be32_to_cpu(past->flags); 2958c2ecf20Sopenharmony_ci node = past->node_idx; 2968c2ecf20Sopenharmony_ci 2978c2ecf20Sopenharmony_ci if (locklen > DLM_LOCKID_NAME_MAX) { 2988c2ecf20Sopenharmony_ci ret = DLM_IVBUFLEN; 2998c2ecf20Sopenharmony_ci mlog(ML_ERROR, "Invalid name length (%d) in proxy ast " 3008c2ecf20Sopenharmony_ci "handler!\n", locklen); 3018c2ecf20Sopenharmony_ci goto leave; 3028c2ecf20Sopenharmony_ci } 3038c2ecf20Sopenharmony_ci 3048c2ecf20Sopenharmony_ci if ((flags & (LKM_PUT_LVB|LKM_GET_LVB)) == 3058c2ecf20Sopenharmony_ci (LKM_PUT_LVB|LKM_GET_LVB)) { 3068c2ecf20Sopenharmony_ci mlog(ML_ERROR, "Both PUT and GET lvb specified, (0x%x)\n", 3078c2ecf20Sopenharmony_ci flags); 3088c2ecf20Sopenharmony_ci ret = DLM_BADARGS; 3098c2ecf20Sopenharmony_ci goto leave; 3108c2ecf20Sopenharmony_ci } 3118c2ecf20Sopenharmony_ci 3128c2ecf20Sopenharmony_ci mlog(0, "lvb: %s\n", flags & LKM_PUT_LVB ? "put lvb" : 3138c2ecf20Sopenharmony_ci (flags & LKM_GET_LVB ? "get lvb" : "none")); 3148c2ecf20Sopenharmony_ci 3158c2ecf20Sopenharmony_ci mlog(0, "type=%d, blocked_type=%d\n", past->type, past->blocked_type); 3168c2ecf20Sopenharmony_ci 3178c2ecf20Sopenharmony_ci if (past->type != DLM_AST && 3188c2ecf20Sopenharmony_ci past->type != DLM_BAST) { 3198c2ecf20Sopenharmony_ci mlog(ML_ERROR, "Unknown ast type! %d, cookie=%u:%llu" 3208c2ecf20Sopenharmony_ci "name=%.*s, node=%u\n", past->type, 3218c2ecf20Sopenharmony_ci dlm_get_lock_cookie_node(be64_to_cpu(cookie)), 3228c2ecf20Sopenharmony_ci dlm_get_lock_cookie_seq(be64_to_cpu(cookie)), 3238c2ecf20Sopenharmony_ci locklen, name, node); 3248c2ecf20Sopenharmony_ci ret = DLM_IVLOCKID; 3258c2ecf20Sopenharmony_ci goto leave; 3268c2ecf20Sopenharmony_ci } 3278c2ecf20Sopenharmony_ci 3288c2ecf20Sopenharmony_ci res = dlm_lookup_lockres(dlm, name, locklen); 3298c2ecf20Sopenharmony_ci if (!res) { 3308c2ecf20Sopenharmony_ci mlog(0, "Got %sast for unknown lockres! cookie=%u:%llu, " 3318c2ecf20Sopenharmony_ci "name=%.*s, node=%u\n", (past->type == DLM_AST ? "" : "b"), 3328c2ecf20Sopenharmony_ci dlm_get_lock_cookie_node(be64_to_cpu(cookie)), 3338c2ecf20Sopenharmony_ci dlm_get_lock_cookie_seq(be64_to_cpu(cookie)), 3348c2ecf20Sopenharmony_ci locklen, name, node); 3358c2ecf20Sopenharmony_ci ret = DLM_IVLOCKID; 3368c2ecf20Sopenharmony_ci goto leave; 3378c2ecf20Sopenharmony_ci } 3388c2ecf20Sopenharmony_ci 3398c2ecf20Sopenharmony_ci /* cannot get a proxy ast message if this node owns it */ 3408c2ecf20Sopenharmony_ci BUG_ON(res->owner == dlm->node_num); 3418c2ecf20Sopenharmony_ci 3428c2ecf20Sopenharmony_ci mlog(0, "%s: res %.*s\n", dlm->name, res->lockname.len, 3438c2ecf20Sopenharmony_ci res->lockname.name); 3448c2ecf20Sopenharmony_ci 3458c2ecf20Sopenharmony_ci spin_lock(&res->spinlock); 3468c2ecf20Sopenharmony_ci if (res->state & DLM_LOCK_RES_RECOVERING) { 3478c2ecf20Sopenharmony_ci mlog(0, "Responding with DLM_RECOVERING!\n"); 3488c2ecf20Sopenharmony_ci ret = DLM_RECOVERING; 3498c2ecf20Sopenharmony_ci goto unlock_out; 3508c2ecf20Sopenharmony_ci } 3518c2ecf20Sopenharmony_ci if (res->state & DLM_LOCK_RES_MIGRATING) { 3528c2ecf20Sopenharmony_ci mlog(0, "Responding with DLM_MIGRATING!\n"); 3538c2ecf20Sopenharmony_ci ret = DLM_MIGRATING; 3548c2ecf20Sopenharmony_ci goto unlock_out; 3558c2ecf20Sopenharmony_ci } 3568c2ecf20Sopenharmony_ci /* try convert queue for both ast/bast */ 3578c2ecf20Sopenharmony_ci head = &res->converting; 3588c2ecf20Sopenharmony_ci lock = NULL; 3598c2ecf20Sopenharmony_ci list_for_each_entry(lock, head, list) { 3608c2ecf20Sopenharmony_ci if (lock->ml.cookie == cookie) 3618c2ecf20Sopenharmony_ci goto do_ast; 3628c2ecf20Sopenharmony_ci } 3638c2ecf20Sopenharmony_ci 3648c2ecf20Sopenharmony_ci /* if not on convert, try blocked for ast, granted for bast */ 3658c2ecf20Sopenharmony_ci if (past->type == DLM_AST) 3668c2ecf20Sopenharmony_ci head = &res->blocked; 3678c2ecf20Sopenharmony_ci else 3688c2ecf20Sopenharmony_ci head = &res->granted; 3698c2ecf20Sopenharmony_ci 3708c2ecf20Sopenharmony_ci list_for_each_entry(lock, head, list) { 3718c2ecf20Sopenharmony_ci /* if lock is found but unlock is pending ignore the bast */ 3728c2ecf20Sopenharmony_ci if (lock->ml.cookie == cookie) { 3738c2ecf20Sopenharmony_ci if (lock->unlock_pending) 3748c2ecf20Sopenharmony_ci break; 3758c2ecf20Sopenharmony_ci goto do_ast; 3768c2ecf20Sopenharmony_ci } 3778c2ecf20Sopenharmony_ci } 3788c2ecf20Sopenharmony_ci 3798c2ecf20Sopenharmony_ci mlog(0, "Got %sast for unknown lock! cookie=%u:%llu, name=%.*s, " 3808c2ecf20Sopenharmony_ci "node=%u\n", past->type == DLM_AST ? "" : "b", 3818c2ecf20Sopenharmony_ci dlm_get_lock_cookie_node(be64_to_cpu(cookie)), 3828c2ecf20Sopenharmony_ci dlm_get_lock_cookie_seq(be64_to_cpu(cookie)), 3838c2ecf20Sopenharmony_ci locklen, name, node); 3848c2ecf20Sopenharmony_ci 3858c2ecf20Sopenharmony_ci ret = DLM_NORMAL; 3868c2ecf20Sopenharmony_ciunlock_out: 3878c2ecf20Sopenharmony_ci spin_unlock(&res->spinlock); 3888c2ecf20Sopenharmony_ci goto leave; 3898c2ecf20Sopenharmony_ci 3908c2ecf20Sopenharmony_cido_ast: 3918c2ecf20Sopenharmony_ci ret = DLM_NORMAL; 3928c2ecf20Sopenharmony_ci if (past->type == DLM_AST) { 3938c2ecf20Sopenharmony_ci /* do not alter lock refcount. switching lists. */ 3948c2ecf20Sopenharmony_ci list_move_tail(&lock->list, &res->granted); 3958c2ecf20Sopenharmony_ci mlog(0, "%s: res %.*s, lock %u:%llu, Granted type %d => %d\n", 3968c2ecf20Sopenharmony_ci dlm->name, res->lockname.len, res->lockname.name, 3978c2ecf20Sopenharmony_ci dlm_get_lock_cookie_node(be64_to_cpu(cookie)), 3988c2ecf20Sopenharmony_ci dlm_get_lock_cookie_seq(be64_to_cpu(cookie)), 3998c2ecf20Sopenharmony_ci lock->ml.type, lock->ml.convert_type); 4008c2ecf20Sopenharmony_ci 4018c2ecf20Sopenharmony_ci if (lock->ml.convert_type != LKM_IVMODE) { 4028c2ecf20Sopenharmony_ci lock->ml.type = lock->ml.convert_type; 4038c2ecf20Sopenharmony_ci lock->ml.convert_type = LKM_IVMODE; 4048c2ecf20Sopenharmony_ci } else { 4058c2ecf20Sopenharmony_ci // should already be there.... 4068c2ecf20Sopenharmony_ci } 4078c2ecf20Sopenharmony_ci 4088c2ecf20Sopenharmony_ci lock->lksb->status = DLM_NORMAL; 4098c2ecf20Sopenharmony_ci 4108c2ecf20Sopenharmony_ci /* if we requested the lvb, fetch it into our lksb now */ 4118c2ecf20Sopenharmony_ci if (flags & LKM_GET_LVB) { 4128c2ecf20Sopenharmony_ci BUG_ON(!(lock->lksb->flags & DLM_LKSB_GET_LVB)); 4138c2ecf20Sopenharmony_ci memcpy(lock->lksb->lvb, past->lvb, DLM_LVB_LEN); 4148c2ecf20Sopenharmony_ci } 4158c2ecf20Sopenharmony_ci } 4168c2ecf20Sopenharmony_ci spin_unlock(&res->spinlock); 4178c2ecf20Sopenharmony_ci 4188c2ecf20Sopenharmony_ci if (past->type == DLM_AST) 4198c2ecf20Sopenharmony_ci dlm_do_local_ast(dlm, res, lock); 4208c2ecf20Sopenharmony_ci else 4218c2ecf20Sopenharmony_ci dlm_do_local_bast(dlm, res, lock, past->blocked_type); 4228c2ecf20Sopenharmony_ci 4238c2ecf20Sopenharmony_cileave: 4248c2ecf20Sopenharmony_ci if (res) 4258c2ecf20Sopenharmony_ci dlm_lockres_put(res); 4268c2ecf20Sopenharmony_ci 4278c2ecf20Sopenharmony_ci dlm_put(dlm); 4288c2ecf20Sopenharmony_ci return ret; 4298c2ecf20Sopenharmony_ci} 4308c2ecf20Sopenharmony_ci 4318c2ecf20Sopenharmony_ci 4328c2ecf20Sopenharmony_ci 4338c2ecf20Sopenharmony_ciint dlm_send_proxy_ast_msg(struct dlm_ctxt *dlm, struct dlm_lock_resource *res, 4348c2ecf20Sopenharmony_ci struct dlm_lock *lock, int msg_type, 4358c2ecf20Sopenharmony_ci int blocked_type, int flags) 4368c2ecf20Sopenharmony_ci{ 4378c2ecf20Sopenharmony_ci int ret = 0; 4388c2ecf20Sopenharmony_ci struct dlm_proxy_ast past; 4398c2ecf20Sopenharmony_ci struct kvec vec[2]; 4408c2ecf20Sopenharmony_ci size_t veclen = 1; 4418c2ecf20Sopenharmony_ci int status; 4428c2ecf20Sopenharmony_ci 4438c2ecf20Sopenharmony_ci mlog(0, "%s: res %.*s, to %u, type %d, blocked_type %d\n", dlm->name, 4448c2ecf20Sopenharmony_ci res->lockname.len, res->lockname.name, lock->ml.node, msg_type, 4458c2ecf20Sopenharmony_ci blocked_type); 4468c2ecf20Sopenharmony_ci 4478c2ecf20Sopenharmony_ci memset(&past, 0, sizeof(struct dlm_proxy_ast)); 4488c2ecf20Sopenharmony_ci past.node_idx = dlm->node_num; 4498c2ecf20Sopenharmony_ci past.type = msg_type; 4508c2ecf20Sopenharmony_ci past.blocked_type = blocked_type; 4518c2ecf20Sopenharmony_ci past.namelen = res->lockname.len; 4528c2ecf20Sopenharmony_ci memcpy(past.name, res->lockname.name, past.namelen); 4538c2ecf20Sopenharmony_ci past.cookie = lock->ml.cookie; 4548c2ecf20Sopenharmony_ci 4558c2ecf20Sopenharmony_ci vec[0].iov_len = sizeof(struct dlm_proxy_ast); 4568c2ecf20Sopenharmony_ci vec[0].iov_base = &past; 4578c2ecf20Sopenharmony_ci if (flags & DLM_LKSB_GET_LVB) { 4588c2ecf20Sopenharmony_ci be32_add_cpu(&past.flags, LKM_GET_LVB); 4598c2ecf20Sopenharmony_ci vec[1].iov_len = DLM_LVB_LEN; 4608c2ecf20Sopenharmony_ci vec[1].iov_base = lock->lksb->lvb; 4618c2ecf20Sopenharmony_ci veclen++; 4628c2ecf20Sopenharmony_ci } 4638c2ecf20Sopenharmony_ci 4648c2ecf20Sopenharmony_ci ret = o2net_send_message_vec(DLM_PROXY_AST_MSG, dlm->key, vec, veclen, 4658c2ecf20Sopenharmony_ci lock->ml.node, &status); 4668c2ecf20Sopenharmony_ci if (ret < 0) 4678c2ecf20Sopenharmony_ci mlog(ML_ERROR, "%s: res %.*s, error %d send AST to node %u\n", 4688c2ecf20Sopenharmony_ci dlm->name, res->lockname.len, res->lockname.name, ret, 4698c2ecf20Sopenharmony_ci lock->ml.node); 4708c2ecf20Sopenharmony_ci else { 4718c2ecf20Sopenharmony_ci if (status == DLM_RECOVERING) { 4728c2ecf20Sopenharmony_ci mlog(ML_ERROR, "sent AST to node %u, it thinks this " 4738c2ecf20Sopenharmony_ci "node is dead!\n", lock->ml.node); 4748c2ecf20Sopenharmony_ci BUG(); 4758c2ecf20Sopenharmony_ci } else if (status == DLM_MIGRATING) { 4768c2ecf20Sopenharmony_ci mlog(ML_ERROR, "sent AST to node %u, it returned " 4778c2ecf20Sopenharmony_ci "DLM_MIGRATING!\n", lock->ml.node); 4788c2ecf20Sopenharmony_ci BUG(); 4798c2ecf20Sopenharmony_ci } else if (status != DLM_NORMAL && status != DLM_IVLOCKID) { 4808c2ecf20Sopenharmony_ci mlog(ML_ERROR, "AST to node %u returned %d!\n", 4818c2ecf20Sopenharmony_ci lock->ml.node, status); 4828c2ecf20Sopenharmony_ci /* ignore it */ 4838c2ecf20Sopenharmony_ci } 4848c2ecf20Sopenharmony_ci ret = 0; 4858c2ecf20Sopenharmony_ci } 4868c2ecf20Sopenharmony_ci return ret; 4878c2ecf20Sopenharmony_ci} 488