18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 28c2ecf20Sopenharmony_ci/****************************************************************************** 38c2ecf20Sopenharmony_ci******************************************************************************* 48c2ecf20Sopenharmony_ci** 58c2ecf20Sopenharmony_ci** Copyright (C) 2005-2007 Red Hat, Inc. All rights reserved. 68c2ecf20Sopenharmony_ci** 78c2ecf20Sopenharmony_ci** 88c2ecf20Sopenharmony_ci******************************************************************************* 98c2ecf20Sopenharmony_ci******************************************************************************/ 108c2ecf20Sopenharmony_ci 118c2ecf20Sopenharmony_ci#include "dlm_internal.h" 128c2ecf20Sopenharmony_ci#include "member.h" 138c2ecf20Sopenharmony_ci#include "lock.h" 148c2ecf20Sopenharmony_ci#include "dir.h" 158c2ecf20Sopenharmony_ci#include "config.h" 168c2ecf20Sopenharmony_ci#include "requestqueue.h" 178c2ecf20Sopenharmony_ci 188c2ecf20Sopenharmony_cistruct rq_entry { 198c2ecf20Sopenharmony_ci struct list_head list; 208c2ecf20Sopenharmony_ci uint32_t recover_seq; 218c2ecf20Sopenharmony_ci int nodeid; 228c2ecf20Sopenharmony_ci struct dlm_message request; 238c2ecf20Sopenharmony_ci}; 248c2ecf20Sopenharmony_ci 258c2ecf20Sopenharmony_ci/* 268c2ecf20Sopenharmony_ci * Requests received while the lockspace is in recovery get added to the 278c2ecf20Sopenharmony_ci * request queue and processed when recovery is complete. This happens when 288c2ecf20Sopenharmony_ci * the lockspace is suspended on some nodes before it is on others, or the 298c2ecf20Sopenharmony_ci * lockspace is enabled on some while still suspended on others. 308c2ecf20Sopenharmony_ci */ 318c2ecf20Sopenharmony_ci 328c2ecf20Sopenharmony_civoid dlm_add_requestqueue(struct dlm_ls *ls, int nodeid, struct dlm_message *ms) 338c2ecf20Sopenharmony_ci{ 348c2ecf20Sopenharmony_ci struct rq_entry *e; 358c2ecf20Sopenharmony_ci int length = ms->m_header.h_length - sizeof(struct dlm_message); 368c2ecf20Sopenharmony_ci 378c2ecf20Sopenharmony_ci e = kmalloc(sizeof(struct rq_entry) + length, GFP_NOFS); 388c2ecf20Sopenharmony_ci if (!e) { 398c2ecf20Sopenharmony_ci log_print("dlm_add_requestqueue: out of memory len %d", length); 408c2ecf20Sopenharmony_ci return; 418c2ecf20Sopenharmony_ci } 428c2ecf20Sopenharmony_ci 438c2ecf20Sopenharmony_ci e->recover_seq = ls->ls_recover_seq & 0xFFFFFFFF; 448c2ecf20Sopenharmony_ci e->nodeid = nodeid; 458c2ecf20Sopenharmony_ci memcpy(&e->request, ms, ms->m_header.h_length); 468c2ecf20Sopenharmony_ci 478c2ecf20Sopenharmony_ci mutex_lock(&ls->ls_requestqueue_mutex); 488c2ecf20Sopenharmony_ci list_add_tail(&e->list, &ls->ls_requestqueue); 498c2ecf20Sopenharmony_ci mutex_unlock(&ls->ls_requestqueue_mutex); 508c2ecf20Sopenharmony_ci} 518c2ecf20Sopenharmony_ci 528c2ecf20Sopenharmony_ci/* 538c2ecf20Sopenharmony_ci * Called by dlm_recoverd to process normal messages saved while recovery was 548c2ecf20Sopenharmony_ci * happening. Normal locking has been enabled before this is called. dlm_recv 558c2ecf20Sopenharmony_ci * upon receiving a message, will wait for all saved messages to be drained 568c2ecf20Sopenharmony_ci * here before processing the message it got. If a new dlm_ls_stop() arrives 578c2ecf20Sopenharmony_ci * while we're processing these saved messages, it may block trying to suspend 588c2ecf20Sopenharmony_ci * dlm_recv if dlm_recv is waiting for us in dlm_wait_requestqueue. In that 598c2ecf20Sopenharmony_ci * case, we don't abort since locking_stopped is still 0. If dlm_recv is not 608c2ecf20Sopenharmony_ci * waiting for us, then this processing may be aborted due to locking_stopped. 618c2ecf20Sopenharmony_ci */ 628c2ecf20Sopenharmony_ci 638c2ecf20Sopenharmony_ciint dlm_process_requestqueue(struct dlm_ls *ls) 648c2ecf20Sopenharmony_ci{ 658c2ecf20Sopenharmony_ci struct rq_entry *e; 668c2ecf20Sopenharmony_ci struct dlm_message *ms; 678c2ecf20Sopenharmony_ci int error = 0; 688c2ecf20Sopenharmony_ci 698c2ecf20Sopenharmony_ci mutex_lock(&ls->ls_requestqueue_mutex); 708c2ecf20Sopenharmony_ci 718c2ecf20Sopenharmony_ci for (;;) { 728c2ecf20Sopenharmony_ci if (list_empty(&ls->ls_requestqueue)) { 738c2ecf20Sopenharmony_ci mutex_unlock(&ls->ls_requestqueue_mutex); 748c2ecf20Sopenharmony_ci error = 0; 758c2ecf20Sopenharmony_ci break; 768c2ecf20Sopenharmony_ci } 778c2ecf20Sopenharmony_ci e = list_entry(ls->ls_requestqueue.next, struct rq_entry, list); 788c2ecf20Sopenharmony_ci mutex_unlock(&ls->ls_requestqueue_mutex); 798c2ecf20Sopenharmony_ci 808c2ecf20Sopenharmony_ci ms = &e->request; 818c2ecf20Sopenharmony_ci 828c2ecf20Sopenharmony_ci log_limit(ls, "dlm_process_requestqueue msg %d from %d " 838c2ecf20Sopenharmony_ci "lkid %x remid %x result %d seq %u", 848c2ecf20Sopenharmony_ci ms->m_type, ms->m_header.h_nodeid, 858c2ecf20Sopenharmony_ci ms->m_lkid, ms->m_remid, ms->m_result, 868c2ecf20Sopenharmony_ci e->recover_seq); 878c2ecf20Sopenharmony_ci 888c2ecf20Sopenharmony_ci dlm_receive_message_saved(ls, &e->request, e->recover_seq); 898c2ecf20Sopenharmony_ci 908c2ecf20Sopenharmony_ci mutex_lock(&ls->ls_requestqueue_mutex); 918c2ecf20Sopenharmony_ci list_del(&e->list); 928c2ecf20Sopenharmony_ci kfree(e); 938c2ecf20Sopenharmony_ci 948c2ecf20Sopenharmony_ci if (dlm_locking_stopped(ls)) { 958c2ecf20Sopenharmony_ci log_debug(ls, "process_requestqueue abort running"); 968c2ecf20Sopenharmony_ci mutex_unlock(&ls->ls_requestqueue_mutex); 978c2ecf20Sopenharmony_ci error = -EINTR; 988c2ecf20Sopenharmony_ci break; 998c2ecf20Sopenharmony_ci } 1008c2ecf20Sopenharmony_ci schedule(); 1018c2ecf20Sopenharmony_ci } 1028c2ecf20Sopenharmony_ci 1038c2ecf20Sopenharmony_ci return error; 1048c2ecf20Sopenharmony_ci} 1058c2ecf20Sopenharmony_ci 1068c2ecf20Sopenharmony_ci/* 1078c2ecf20Sopenharmony_ci * After recovery is done, locking is resumed and dlm_recoverd takes all the 1088c2ecf20Sopenharmony_ci * saved requests and processes them as they would have been by dlm_recv. At 1098c2ecf20Sopenharmony_ci * the same time, dlm_recv will start receiving new requests from remote nodes. 1108c2ecf20Sopenharmony_ci * We want to delay dlm_recv processing new requests until dlm_recoverd has 1118c2ecf20Sopenharmony_ci * finished processing the old saved requests. We don't check for locking 1128c2ecf20Sopenharmony_ci * stopped here because dlm_ls_stop won't stop locking until it's suspended us 1138c2ecf20Sopenharmony_ci * (dlm_recv). 1148c2ecf20Sopenharmony_ci */ 1158c2ecf20Sopenharmony_ci 1168c2ecf20Sopenharmony_civoid dlm_wait_requestqueue(struct dlm_ls *ls) 1178c2ecf20Sopenharmony_ci{ 1188c2ecf20Sopenharmony_ci for (;;) { 1198c2ecf20Sopenharmony_ci mutex_lock(&ls->ls_requestqueue_mutex); 1208c2ecf20Sopenharmony_ci if (list_empty(&ls->ls_requestqueue)) 1218c2ecf20Sopenharmony_ci break; 1228c2ecf20Sopenharmony_ci mutex_unlock(&ls->ls_requestqueue_mutex); 1238c2ecf20Sopenharmony_ci schedule(); 1248c2ecf20Sopenharmony_ci } 1258c2ecf20Sopenharmony_ci mutex_unlock(&ls->ls_requestqueue_mutex); 1268c2ecf20Sopenharmony_ci} 1278c2ecf20Sopenharmony_ci 1288c2ecf20Sopenharmony_cistatic int purge_request(struct dlm_ls *ls, struct dlm_message *ms, int nodeid) 1298c2ecf20Sopenharmony_ci{ 1308c2ecf20Sopenharmony_ci uint32_t type = ms->m_type; 1318c2ecf20Sopenharmony_ci 1328c2ecf20Sopenharmony_ci /* the ls is being cleaned up and freed by release_lockspace */ 1338c2ecf20Sopenharmony_ci if (!ls->ls_count) 1348c2ecf20Sopenharmony_ci return 1; 1358c2ecf20Sopenharmony_ci 1368c2ecf20Sopenharmony_ci if (dlm_is_removed(ls, nodeid)) 1378c2ecf20Sopenharmony_ci return 1; 1388c2ecf20Sopenharmony_ci 1398c2ecf20Sopenharmony_ci /* directory operations are always purged because the directory is 1408c2ecf20Sopenharmony_ci always rebuilt during recovery and the lookups resent */ 1418c2ecf20Sopenharmony_ci 1428c2ecf20Sopenharmony_ci if (type == DLM_MSG_REMOVE || 1438c2ecf20Sopenharmony_ci type == DLM_MSG_LOOKUP || 1448c2ecf20Sopenharmony_ci type == DLM_MSG_LOOKUP_REPLY) 1458c2ecf20Sopenharmony_ci return 1; 1468c2ecf20Sopenharmony_ci 1478c2ecf20Sopenharmony_ci if (!dlm_no_directory(ls)) 1488c2ecf20Sopenharmony_ci return 0; 1498c2ecf20Sopenharmony_ci 1508c2ecf20Sopenharmony_ci return 1; 1518c2ecf20Sopenharmony_ci} 1528c2ecf20Sopenharmony_ci 1538c2ecf20Sopenharmony_civoid dlm_purge_requestqueue(struct dlm_ls *ls) 1548c2ecf20Sopenharmony_ci{ 1558c2ecf20Sopenharmony_ci struct dlm_message *ms; 1568c2ecf20Sopenharmony_ci struct rq_entry *e, *safe; 1578c2ecf20Sopenharmony_ci 1588c2ecf20Sopenharmony_ci mutex_lock(&ls->ls_requestqueue_mutex); 1598c2ecf20Sopenharmony_ci list_for_each_entry_safe(e, safe, &ls->ls_requestqueue, list) { 1608c2ecf20Sopenharmony_ci ms = &e->request; 1618c2ecf20Sopenharmony_ci 1628c2ecf20Sopenharmony_ci if (purge_request(ls, ms, e->nodeid)) { 1638c2ecf20Sopenharmony_ci list_del(&e->list); 1648c2ecf20Sopenharmony_ci kfree(e); 1658c2ecf20Sopenharmony_ci } 1668c2ecf20Sopenharmony_ci } 1678c2ecf20Sopenharmony_ci mutex_unlock(&ls->ls_requestqueue_mutex); 1688c2ecf20Sopenharmony_ci} 1698c2ecf20Sopenharmony_ci 170