162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 262306a36Sopenharmony_ci/****************************************************************************** 362306a36Sopenharmony_ci******************************************************************************* 462306a36Sopenharmony_ci** 562306a36Sopenharmony_ci** Copyright (C) 2005-2010 Red Hat, Inc. All rights reserved. 662306a36Sopenharmony_ci** 762306a36Sopenharmony_ci** 862306a36Sopenharmony_ci******************************************************************************* 962306a36Sopenharmony_ci******************************************************************************/ 1062306a36Sopenharmony_ci 1162306a36Sopenharmony_ci/* Central locking logic has four stages: 1262306a36Sopenharmony_ci 1362306a36Sopenharmony_ci dlm_lock() 1462306a36Sopenharmony_ci dlm_unlock() 1562306a36Sopenharmony_ci 1662306a36Sopenharmony_ci request_lock(ls, lkb) 1762306a36Sopenharmony_ci convert_lock(ls, lkb) 1862306a36Sopenharmony_ci unlock_lock(ls, lkb) 1962306a36Sopenharmony_ci cancel_lock(ls, lkb) 2062306a36Sopenharmony_ci 2162306a36Sopenharmony_ci _request_lock(r, lkb) 2262306a36Sopenharmony_ci _convert_lock(r, lkb) 2362306a36Sopenharmony_ci _unlock_lock(r, lkb) 2462306a36Sopenharmony_ci _cancel_lock(r, lkb) 2562306a36Sopenharmony_ci 2662306a36Sopenharmony_ci do_request(r, lkb) 2762306a36Sopenharmony_ci do_convert(r, lkb) 2862306a36Sopenharmony_ci do_unlock(r, lkb) 2962306a36Sopenharmony_ci do_cancel(r, lkb) 3062306a36Sopenharmony_ci 3162306a36Sopenharmony_ci Stage 1 (lock, unlock) is mainly about checking input args and 3262306a36Sopenharmony_ci splitting into one of the four main operations: 3362306a36Sopenharmony_ci 3462306a36Sopenharmony_ci dlm_lock = request_lock 3562306a36Sopenharmony_ci dlm_lock+CONVERT = convert_lock 3662306a36Sopenharmony_ci dlm_unlock = unlock_lock 3762306a36Sopenharmony_ci dlm_unlock+CANCEL = cancel_lock 3862306a36Sopenharmony_ci 3962306a36Sopenharmony_ci Stage 2, xxxx_lock(), just finds and locks the relevant rsb which is 4062306a36Sopenharmony_ci provided to the next stage. 4162306a36Sopenharmony_ci 4262306a36Sopenharmony_ci Stage 3, _xxxx_lock(), determines if the operation is local or remote. 4362306a36Sopenharmony_ci When remote, it calls send_xxxx(), when local it calls do_xxxx(). 4462306a36Sopenharmony_ci 4562306a36Sopenharmony_ci Stage 4, do_xxxx(), is the guts of the operation. It manipulates the 4662306a36Sopenharmony_ci given rsb and lkb and queues callbacks. 4762306a36Sopenharmony_ci 4862306a36Sopenharmony_ci For remote operations, send_xxxx() results in the corresponding do_xxxx() 4962306a36Sopenharmony_ci function being executed on the remote node. The connecting send/receive 5062306a36Sopenharmony_ci calls on local (L) and remote (R) nodes: 5162306a36Sopenharmony_ci 5262306a36Sopenharmony_ci L: send_xxxx() -> R: receive_xxxx() 5362306a36Sopenharmony_ci R: do_xxxx() 5462306a36Sopenharmony_ci L: receive_xxxx_reply() <- R: send_xxxx_reply() 5562306a36Sopenharmony_ci*/ 5662306a36Sopenharmony_ci#include <trace/events/dlm.h> 5762306a36Sopenharmony_ci 5862306a36Sopenharmony_ci#include <linux/types.h> 5962306a36Sopenharmony_ci#include <linux/rbtree.h> 6062306a36Sopenharmony_ci#include <linux/slab.h> 6162306a36Sopenharmony_ci#include "dlm_internal.h" 6262306a36Sopenharmony_ci#include <linux/dlm_device.h> 6362306a36Sopenharmony_ci#include "memory.h" 6462306a36Sopenharmony_ci#include "midcomms.h" 6562306a36Sopenharmony_ci#include "requestqueue.h" 6662306a36Sopenharmony_ci#include "util.h" 6762306a36Sopenharmony_ci#include "dir.h" 6862306a36Sopenharmony_ci#include "member.h" 6962306a36Sopenharmony_ci#include "lockspace.h" 7062306a36Sopenharmony_ci#include "ast.h" 7162306a36Sopenharmony_ci#include "lock.h" 7262306a36Sopenharmony_ci#include "rcom.h" 7362306a36Sopenharmony_ci#include "recover.h" 7462306a36Sopenharmony_ci#include "lvb_table.h" 7562306a36Sopenharmony_ci#include "user.h" 7662306a36Sopenharmony_ci#include "config.h" 7762306a36Sopenharmony_ci 7862306a36Sopenharmony_cistatic int send_request(struct dlm_rsb *r, struct dlm_lkb *lkb); 7962306a36Sopenharmony_cistatic int send_convert(struct dlm_rsb *r, struct dlm_lkb *lkb); 8062306a36Sopenharmony_cistatic int send_unlock(struct dlm_rsb *r, struct dlm_lkb *lkb); 8162306a36Sopenharmony_cistatic int send_cancel(struct dlm_rsb *r, struct dlm_lkb *lkb); 8262306a36Sopenharmony_cistatic int send_grant(struct dlm_rsb *r, struct dlm_lkb *lkb); 8362306a36Sopenharmony_cistatic int send_bast(struct dlm_rsb *r, struct dlm_lkb *lkb, int mode); 8462306a36Sopenharmony_cistatic int send_lookup(struct dlm_rsb *r, struct dlm_lkb *lkb); 8562306a36Sopenharmony_cistatic int send_remove(struct dlm_rsb *r); 8662306a36Sopenharmony_cistatic int _request_lock(struct dlm_rsb *r, struct dlm_lkb *lkb); 8762306a36Sopenharmony_cistatic int _cancel_lock(struct dlm_rsb *r, struct dlm_lkb *lkb); 8862306a36Sopenharmony_cistatic void __receive_convert_reply(struct dlm_rsb *r, struct dlm_lkb *lkb, 8962306a36Sopenharmony_ci const struct dlm_message *ms, bool local); 9062306a36Sopenharmony_cistatic int receive_extralen(const struct dlm_message *ms); 9162306a36Sopenharmony_cistatic void do_purge(struct dlm_ls *ls, int nodeid, int pid); 9262306a36Sopenharmony_cistatic void toss_rsb(struct kref *kref); 9362306a36Sopenharmony_ci 9462306a36Sopenharmony_ci/* 9562306a36Sopenharmony_ci * Lock compatibilty matrix - thanks Steve 9662306a36Sopenharmony_ci * UN = Unlocked state. Not really a state, used as a flag 9762306a36Sopenharmony_ci * PD = Padding. Used to make the matrix a nice power of two in size 9862306a36Sopenharmony_ci * Other states are the same as the VMS DLM. 9962306a36Sopenharmony_ci * Usage: matrix[grmode+1][rqmode+1] (although m[rq+1][gr+1] is the same) 10062306a36Sopenharmony_ci */ 10162306a36Sopenharmony_ci 10262306a36Sopenharmony_cistatic const int __dlm_compat_matrix[8][8] = { 10362306a36Sopenharmony_ci /* UN NL CR CW PR PW EX PD */ 10462306a36Sopenharmony_ci {1, 1, 1, 1, 1, 1, 1, 0}, /* UN */ 10562306a36Sopenharmony_ci {1, 1, 1, 1, 1, 1, 1, 0}, /* NL */ 10662306a36Sopenharmony_ci {1, 1, 1, 1, 1, 1, 0, 0}, /* CR */ 10762306a36Sopenharmony_ci {1, 1, 1, 1, 0, 0, 0, 0}, /* CW */ 10862306a36Sopenharmony_ci {1, 1, 1, 0, 1, 0, 0, 0}, /* PR */ 10962306a36Sopenharmony_ci {1, 1, 1, 0, 0, 0, 0, 0}, /* PW */ 11062306a36Sopenharmony_ci {1, 1, 0, 0, 0, 0, 0, 0}, /* EX */ 11162306a36Sopenharmony_ci {0, 0, 0, 0, 0, 0, 0, 0} /* PD */ 11262306a36Sopenharmony_ci}; 11362306a36Sopenharmony_ci 11462306a36Sopenharmony_ci/* 11562306a36Sopenharmony_ci * This defines the direction of transfer of LVB data. 11662306a36Sopenharmony_ci * Granted mode is the row; requested mode is the column. 11762306a36Sopenharmony_ci * Usage: matrix[grmode+1][rqmode+1] 11862306a36Sopenharmony_ci * 1 = LVB is returned to the caller 11962306a36Sopenharmony_ci * 0 = LVB is written to the resource 12062306a36Sopenharmony_ci * -1 = nothing happens to the LVB 12162306a36Sopenharmony_ci */ 12262306a36Sopenharmony_ci 12362306a36Sopenharmony_ciconst int dlm_lvb_operations[8][8] = { 12462306a36Sopenharmony_ci /* UN NL CR CW PR PW EX PD*/ 12562306a36Sopenharmony_ci { -1, 1, 1, 1, 1, 1, 1, -1 }, /* UN */ 12662306a36Sopenharmony_ci { -1, 1, 1, 1, 1, 1, 1, 0 }, /* NL */ 12762306a36Sopenharmony_ci { -1, -1, 1, 1, 1, 1, 1, 0 }, /* CR */ 12862306a36Sopenharmony_ci { -1, -1, -1, 1, 1, 1, 1, 0 }, /* CW */ 12962306a36Sopenharmony_ci { -1, -1, -1, -1, 1, 1, 1, 0 }, /* PR */ 13062306a36Sopenharmony_ci { -1, 0, 0, 0, 0, 0, 1, 0 }, /* PW */ 13162306a36Sopenharmony_ci { -1, 0, 0, 0, 0, 0, 0, 0 }, /* EX */ 13262306a36Sopenharmony_ci { -1, 0, 0, 0, 0, 0, 0, 0 } /* PD */ 13362306a36Sopenharmony_ci}; 13462306a36Sopenharmony_ci 13562306a36Sopenharmony_ci#define modes_compat(gr, rq) \ 13662306a36Sopenharmony_ci __dlm_compat_matrix[(gr)->lkb_grmode + 1][(rq)->lkb_rqmode + 1] 13762306a36Sopenharmony_ci 13862306a36Sopenharmony_ciint dlm_modes_compat(int mode1, int mode2) 13962306a36Sopenharmony_ci{ 14062306a36Sopenharmony_ci return __dlm_compat_matrix[mode1 + 1][mode2 + 1]; 14162306a36Sopenharmony_ci} 14262306a36Sopenharmony_ci 14362306a36Sopenharmony_ci/* 14462306a36Sopenharmony_ci * Compatibility matrix for conversions with QUECVT set. 14562306a36Sopenharmony_ci * Granted mode is the row; requested mode is the column. 14662306a36Sopenharmony_ci * Usage: matrix[grmode+1][rqmode+1] 14762306a36Sopenharmony_ci */ 14862306a36Sopenharmony_ci 14962306a36Sopenharmony_cistatic const int __quecvt_compat_matrix[8][8] = { 15062306a36Sopenharmony_ci /* UN NL CR CW PR PW EX PD */ 15162306a36Sopenharmony_ci {0, 0, 0, 0, 0, 0, 0, 0}, /* UN */ 15262306a36Sopenharmony_ci {0, 0, 1, 1, 1, 1, 1, 0}, /* NL */ 15362306a36Sopenharmony_ci {0, 0, 0, 1, 1, 1, 1, 0}, /* CR */ 15462306a36Sopenharmony_ci {0, 0, 0, 0, 1, 1, 1, 0}, /* CW */ 15562306a36Sopenharmony_ci {0, 0, 0, 1, 0, 1, 1, 0}, /* PR */ 15662306a36Sopenharmony_ci {0, 0, 0, 0, 0, 0, 1, 0}, /* PW */ 15762306a36Sopenharmony_ci {0, 0, 0, 0, 0, 0, 0, 0}, /* EX */ 15862306a36Sopenharmony_ci {0, 0, 0, 0, 0, 0, 0, 0} /* PD */ 15962306a36Sopenharmony_ci}; 16062306a36Sopenharmony_ci 16162306a36Sopenharmony_civoid dlm_print_lkb(struct dlm_lkb *lkb) 16262306a36Sopenharmony_ci{ 16362306a36Sopenharmony_ci printk(KERN_ERR "lkb: nodeid %d id %x remid %x exflags %x flags %x " 16462306a36Sopenharmony_ci "sts %d rq %d gr %d wait_type %d wait_nodeid %d seq %llu\n", 16562306a36Sopenharmony_ci lkb->lkb_nodeid, lkb->lkb_id, lkb->lkb_remid, lkb->lkb_exflags, 16662306a36Sopenharmony_ci dlm_iflags_val(lkb), lkb->lkb_status, lkb->lkb_rqmode, 16762306a36Sopenharmony_ci lkb->lkb_grmode, lkb->lkb_wait_type, lkb->lkb_wait_nodeid, 16862306a36Sopenharmony_ci (unsigned long long)lkb->lkb_recover_seq); 16962306a36Sopenharmony_ci} 17062306a36Sopenharmony_ci 17162306a36Sopenharmony_cistatic void dlm_print_rsb(struct dlm_rsb *r) 17262306a36Sopenharmony_ci{ 17362306a36Sopenharmony_ci printk(KERN_ERR "rsb: nodeid %d master %d dir %d flags %lx first %x " 17462306a36Sopenharmony_ci "rlc %d name %s\n", 17562306a36Sopenharmony_ci r->res_nodeid, r->res_master_nodeid, r->res_dir_nodeid, 17662306a36Sopenharmony_ci r->res_flags, r->res_first_lkid, r->res_recover_locks_count, 17762306a36Sopenharmony_ci r->res_name); 17862306a36Sopenharmony_ci} 17962306a36Sopenharmony_ci 18062306a36Sopenharmony_civoid dlm_dump_rsb(struct dlm_rsb *r) 18162306a36Sopenharmony_ci{ 18262306a36Sopenharmony_ci struct dlm_lkb *lkb; 18362306a36Sopenharmony_ci 18462306a36Sopenharmony_ci dlm_print_rsb(r); 18562306a36Sopenharmony_ci 18662306a36Sopenharmony_ci printk(KERN_ERR "rsb: root_list empty %d recover_list empty %d\n", 18762306a36Sopenharmony_ci list_empty(&r->res_root_list), list_empty(&r->res_recover_list)); 18862306a36Sopenharmony_ci printk(KERN_ERR "rsb lookup list\n"); 18962306a36Sopenharmony_ci list_for_each_entry(lkb, &r->res_lookup, lkb_rsb_lookup) 19062306a36Sopenharmony_ci dlm_print_lkb(lkb); 19162306a36Sopenharmony_ci printk(KERN_ERR "rsb grant queue:\n"); 19262306a36Sopenharmony_ci list_for_each_entry(lkb, &r->res_grantqueue, lkb_statequeue) 19362306a36Sopenharmony_ci dlm_print_lkb(lkb); 19462306a36Sopenharmony_ci printk(KERN_ERR "rsb convert queue:\n"); 19562306a36Sopenharmony_ci list_for_each_entry(lkb, &r->res_convertqueue, lkb_statequeue) 19662306a36Sopenharmony_ci dlm_print_lkb(lkb); 19762306a36Sopenharmony_ci printk(KERN_ERR "rsb wait queue:\n"); 19862306a36Sopenharmony_ci list_for_each_entry(lkb, &r->res_waitqueue, lkb_statequeue) 19962306a36Sopenharmony_ci dlm_print_lkb(lkb); 20062306a36Sopenharmony_ci} 20162306a36Sopenharmony_ci 20262306a36Sopenharmony_ci/* Threads cannot use the lockspace while it's being recovered */ 20362306a36Sopenharmony_ci 20462306a36Sopenharmony_cistatic inline void dlm_lock_recovery(struct dlm_ls *ls) 20562306a36Sopenharmony_ci{ 20662306a36Sopenharmony_ci down_read(&ls->ls_in_recovery); 20762306a36Sopenharmony_ci} 20862306a36Sopenharmony_ci 20962306a36Sopenharmony_civoid dlm_unlock_recovery(struct dlm_ls *ls) 21062306a36Sopenharmony_ci{ 21162306a36Sopenharmony_ci up_read(&ls->ls_in_recovery); 21262306a36Sopenharmony_ci} 21362306a36Sopenharmony_ci 21462306a36Sopenharmony_ciint dlm_lock_recovery_try(struct dlm_ls *ls) 21562306a36Sopenharmony_ci{ 21662306a36Sopenharmony_ci return down_read_trylock(&ls->ls_in_recovery); 21762306a36Sopenharmony_ci} 21862306a36Sopenharmony_ci 21962306a36Sopenharmony_cistatic inline int can_be_queued(struct dlm_lkb *lkb) 22062306a36Sopenharmony_ci{ 22162306a36Sopenharmony_ci return !(lkb->lkb_exflags & DLM_LKF_NOQUEUE); 22262306a36Sopenharmony_ci} 22362306a36Sopenharmony_ci 22462306a36Sopenharmony_cistatic inline int force_blocking_asts(struct dlm_lkb *lkb) 22562306a36Sopenharmony_ci{ 22662306a36Sopenharmony_ci return (lkb->lkb_exflags & DLM_LKF_NOQUEUEBAST); 22762306a36Sopenharmony_ci} 22862306a36Sopenharmony_ci 22962306a36Sopenharmony_cistatic inline int is_demoted(struct dlm_lkb *lkb) 23062306a36Sopenharmony_ci{ 23162306a36Sopenharmony_ci return test_bit(DLM_SBF_DEMOTED_BIT, &lkb->lkb_sbflags); 23262306a36Sopenharmony_ci} 23362306a36Sopenharmony_ci 23462306a36Sopenharmony_cistatic inline int is_altmode(struct dlm_lkb *lkb) 23562306a36Sopenharmony_ci{ 23662306a36Sopenharmony_ci return test_bit(DLM_SBF_ALTMODE_BIT, &lkb->lkb_sbflags); 23762306a36Sopenharmony_ci} 23862306a36Sopenharmony_ci 23962306a36Sopenharmony_cistatic inline int is_granted(struct dlm_lkb *lkb) 24062306a36Sopenharmony_ci{ 24162306a36Sopenharmony_ci return (lkb->lkb_status == DLM_LKSTS_GRANTED); 24262306a36Sopenharmony_ci} 24362306a36Sopenharmony_ci 24462306a36Sopenharmony_cistatic inline int is_remote(struct dlm_rsb *r) 24562306a36Sopenharmony_ci{ 24662306a36Sopenharmony_ci DLM_ASSERT(r->res_nodeid >= 0, dlm_print_rsb(r);); 24762306a36Sopenharmony_ci return !!r->res_nodeid; 24862306a36Sopenharmony_ci} 24962306a36Sopenharmony_ci 25062306a36Sopenharmony_cistatic inline int is_process_copy(struct dlm_lkb *lkb) 25162306a36Sopenharmony_ci{ 25262306a36Sopenharmony_ci return lkb->lkb_nodeid && 25362306a36Sopenharmony_ci !test_bit(DLM_IFL_MSTCPY_BIT, &lkb->lkb_iflags); 25462306a36Sopenharmony_ci} 25562306a36Sopenharmony_ci 25662306a36Sopenharmony_cistatic inline int is_master_copy(struct dlm_lkb *lkb) 25762306a36Sopenharmony_ci{ 25862306a36Sopenharmony_ci return test_bit(DLM_IFL_MSTCPY_BIT, &lkb->lkb_iflags); 25962306a36Sopenharmony_ci} 26062306a36Sopenharmony_ci 26162306a36Sopenharmony_cistatic inline int middle_conversion(struct dlm_lkb *lkb) 26262306a36Sopenharmony_ci{ 26362306a36Sopenharmony_ci if ((lkb->lkb_grmode==DLM_LOCK_PR && lkb->lkb_rqmode==DLM_LOCK_CW) || 26462306a36Sopenharmony_ci (lkb->lkb_rqmode==DLM_LOCK_PR && lkb->lkb_grmode==DLM_LOCK_CW)) 26562306a36Sopenharmony_ci return 1; 26662306a36Sopenharmony_ci return 0; 26762306a36Sopenharmony_ci} 26862306a36Sopenharmony_ci 26962306a36Sopenharmony_cistatic inline int down_conversion(struct dlm_lkb *lkb) 27062306a36Sopenharmony_ci{ 27162306a36Sopenharmony_ci return (!middle_conversion(lkb) && lkb->lkb_rqmode < lkb->lkb_grmode); 27262306a36Sopenharmony_ci} 27362306a36Sopenharmony_ci 27462306a36Sopenharmony_cistatic inline int is_overlap_unlock(struct dlm_lkb *lkb) 27562306a36Sopenharmony_ci{ 27662306a36Sopenharmony_ci return test_bit(DLM_IFL_OVERLAP_UNLOCK_BIT, &lkb->lkb_iflags); 27762306a36Sopenharmony_ci} 27862306a36Sopenharmony_ci 27962306a36Sopenharmony_cistatic inline int is_overlap_cancel(struct dlm_lkb *lkb) 28062306a36Sopenharmony_ci{ 28162306a36Sopenharmony_ci return test_bit(DLM_IFL_OVERLAP_CANCEL_BIT, &lkb->lkb_iflags); 28262306a36Sopenharmony_ci} 28362306a36Sopenharmony_ci 28462306a36Sopenharmony_cistatic inline int is_overlap(struct dlm_lkb *lkb) 28562306a36Sopenharmony_ci{ 28662306a36Sopenharmony_ci return test_bit(DLM_IFL_OVERLAP_UNLOCK_BIT, &lkb->lkb_iflags) || 28762306a36Sopenharmony_ci test_bit(DLM_IFL_OVERLAP_CANCEL_BIT, &lkb->lkb_iflags); 28862306a36Sopenharmony_ci} 28962306a36Sopenharmony_ci 29062306a36Sopenharmony_cistatic void queue_cast(struct dlm_rsb *r, struct dlm_lkb *lkb, int rv) 29162306a36Sopenharmony_ci{ 29262306a36Sopenharmony_ci if (is_master_copy(lkb)) 29362306a36Sopenharmony_ci return; 29462306a36Sopenharmony_ci 29562306a36Sopenharmony_ci DLM_ASSERT(lkb->lkb_lksb, dlm_print_lkb(lkb);); 29662306a36Sopenharmony_ci 29762306a36Sopenharmony_ci if (rv == -DLM_ECANCEL && 29862306a36Sopenharmony_ci test_and_clear_bit(DLM_IFL_DEADLOCK_CANCEL_BIT, &lkb->lkb_iflags)) 29962306a36Sopenharmony_ci rv = -EDEADLK; 30062306a36Sopenharmony_ci 30162306a36Sopenharmony_ci dlm_add_cb(lkb, DLM_CB_CAST, lkb->lkb_grmode, rv, dlm_sbflags_val(lkb)); 30262306a36Sopenharmony_ci} 30362306a36Sopenharmony_ci 30462306a36Sopenharmony_cistatic inline void queue_cast_overlap(struct dlm_rsb *r, struct dlm_lkb *lkb) 30562306a36Sopenharmony_ci{ 30662306a36Sopenharmony_ci queue_cast(r, lkb, 30762306a36Sopenharmony_ci is_overlap_unlock(lkb) ? -DLM_EUNLOCK : -DLM_ECANCEL); 30862306a36Sopenharmony_ci} 30962306a36Sopenharmony_ci 31062306a36Sopenharmony_cistatic void queue_bast(struct dlm_rsb *r, struct dlm_lkb *lkb, int rqmode) 31162306a36Sopenharmony_ci{ 31262306a36Sopenharmony_ci if (is_master_copy(lkb)) { 31362306a36Sopenharmony_ci send_bast(r, lkb, rqmode); 31462306a36Sopenharmony_ci } else { 31562306a36Sopenharmony_ci dlm_add_cb(lkb, DLM_CB_BAST, rqmode, 0, 0); 31662306a36Sopenharmony_ci } 31762306a36Sopenharmony_ci} 31862306a36Sopenharmony_ci 31962306a36Sopenharmony_ci/* 32062306a36Sopenharmony_ci * Basic operations on rsb's and lkb's 32162306a36Sopenharmony_ci */ 32262306a36Sopenharmony_ci 32362306a36Sopenharmony_ci/* This is only called to add a reference when the code already holds 32462306a36Sopenharmony_ci a valid reference to the rsb, so there's no need for locking. */ 32562306a36Sopenharmony_ci 32662306a36Sopenharmony_cistatic inline void hold_rsb(struct dlm_rsb *r) 32762306a36Sopenharmony_ci{ 32862306a36Sopenharmony_ci kref_get(&r->res_ref); 32962306a36Sopenharmony_ci} 33062306a36Sopenharmony_ci 33162306a36Sopenharmony_civoid dlm_hold_rsb(struct dlm_rsb *r) 33262306a36Sopenharmony_ci{ 33362306a36Sopenharmony_ci hold_rsb(r); 33462306a36Sopenharmony_ci} 33562306a36Sopenharmony_ci 33662306a36Sopenharmony_ci/* When all references to the rsb are gone it's transferred to 33762306a36Sopenharmony_ci the tossed list for later disposal. */ 33862306a36Sopenharmony_ci 33962306a36Sopenharmony_cistatic void put_rsb(struct dlm_rsb *r) 34062306a36Sopenharmony_ci{ 34162306a36Sopenharmony_ci struct dlm_ls *ls = r->res_ls; 34262306a36Sopenharmony_ci uint32_t bucket = r->res_bucket; 34362306a36Sopenharmony_ci int rv; 34462306a36Sopenharmony_ci 34562306a36Sopenharmony_ci rv = kref_put_lock(&r->res_ref, toss_rsb, 34662306a36Sopenharmony_ci &ls->ls_rsbtbl[bucket].lock); 34762306a36Sopenharmony_ci if (rv) 34862306a36Sopenharmony_ci spin_unlock(&ls->ls_rsbtbl[bucket].lock); 34962306a36Sopenharmony_ci} 35062306a36Sopenharmony_ci 35162306a36Sopenharmony_civoid dlm_put_rsb(struct dlm_rsb *r) 35262306a36Sopenharmony_ci{ 35362306a36Sopenharmony_ci put_rsb(r); 35462306a36Sopenharmony_ci} 35562306a36Sopenharmony_ci 35662306a36Sopenharmony_cistatic int pre_rsb_struct(struct dlm_ls *ls) 35762306a36Sopenharmony_ci{ 35862306a36Sopenharmony_ci struct dlm_rsb *r1, *r2; 35962306a36Sopenharmony_ci int count = 0; 36062306a36Sopenharmony_ci 36162306a36Sopenharmony_ci spin_lock(&ls->ls_new_rsb_spin); 36262306a36Sopenharmony_ci if (ls->ls_new_rsb_count > dlm_config.ci_new_rsb_count / 2) { 36362306a36Sopenharmony_ci spin_unlock(&ls->ls_new_rsb_spin); 36462306a36Sopenharmony_ci return 0; 36562306a36Sopenharmony_ci } 36662306a36Sopenharmony_ci spin_unlock(&ls->ls_new_rsb_spin); 36762306a36Sopenharmony_ci 36862306a36Sopenharmony_ci r1 = dlm_allocate_rsb(ls); 36962306a36Sopenharmony_ci r2 = dlm_allocate_rsb(ls); 37062306a36Sopenharmony_ci 37162306a36Sopenharmony_ci spin_lock(&ls->ls_new_rsb_spin); 37262306a36Sopenharmony_ci if (r1) { 37362306a36Sopenharmony_ci list_add(&r1->res_hashchain, &ls->ls_new_rsb); 37462306a36Sopenharmony_ci ls->ls_new_rsb_count++; 37562306a36Sopenharmony_ci } 37662306a36Sopenharmony_ci if (r2) { 37762306a36Sopenharmony_ci list_add(&r2->res_hashchain, &ls->ls_new_rsb); 37862306a36Sopenharmony_ci ls->ls_new_rsb_count++; 37962306a36Sopenharmony_ci } 38062306a36Sopenharmony_ci count = ls->ls_new_rsb_count; 38162306a36Sopenharmony_ci spin_unlock(&ls->ls_new_rsb_spin); 38262306a36Sopenharmony_ci 38362306a36Sopenharmony_ci if (!count) 38462306a36Sopenharmony_ci return -ENOMEM; 38562306a36Sopenharmony_ci return 0; 38662306a36Sopenharmony_ci} 38762306a36Sopenharmony_ci 38862306a36Sopenharmony_ci/* If ls->ls_new_rsb is empty, return -EAGAIN, so the caller can 38962306a36Sopenharmony_ci unlock any spinlocks, go back and call pre_rsb_struct again. 39062306a36Sopenharmony_ci Otherwise, take an rsb off the list and return it. */ 39162306a36Sopenharmony_ci 39262306a36Sopenharmony_cistatic int get_rsb_struct(struct dlm_ls *ls, const void *name, int len, 39362306a36Sopenharmony_ci struct dlm_rsb **r_ret) 39462306a36Sopenharmony_ci{ 39562306a36Sopenharmony_ci struct dlm_rsb *r; 39662306a36Sopenharmony_ci int count; 39762306a36Sopenharmony_ci 39862306a36Sopenharmony_ci spin_lock(&ls->ls_new_rsb_spin); 39962306a36Sopenharmony_ci if (list_empty(&ls->ls_new_rsb)) { 40062306a36Sopenharmony_ci count = ls->ls_new_rsb_count; 40162306a36Sopenharmony_ci spin_unlock(&ls->ls_new_rsb_spin); 40262306a36Sopenharmony_ci log_debug(ls, "find_rsb retry %d %d %s", 40362306a36Sopenharmony_ci count, dlm_config.ci_new_rsb_count, 40462306a36Sopenharmony_ci (const char *)name); 40562306a36Sopenharmony_ci return -EAGAIN; 40662306a36Sopenharmony_ci } 40762306a36Sopenharmony_ci 40862306a36Sopenharmony_ci r = list_first_entry(&ls->ls_new_rsb, struct dlm_rsb, res_hashchain); 40962306a36Sopenharmony_ci list_del(&r->res_hashchain); 41062306a36Sopenharmony_ci /* Convert the empty list_head to a NULL rb_node for tree usage: */ 41162306a36Sopenharmony_ci memset(&r->res_hashnode, 0, sizeof(struct rb_node)); 41262306a36Sopenharmony_ci ls->ls_new_rsb_count--; 41362306a36Sopenharmony_ci spin_unlock(&ls->ls_new_rsb_spin); 41462306a36Sopenharmony_ci 41562306a36Sopenharmony_ci r->res_ls = ls; 41662306a36Sopenharmony_ci r->res_length = len; 41762306a36Sopenharmony_ci memcpy(r->res_name, name, len); 41862306a36Sopenharmony_ci mutex_init(&r->res_mutex); 41962306a36Sopenharmony_ci 42062306a36Sopenharmony_ci INIT_LIST_HEAD(&r->res_lookup); 42162306a36Sopenharmony_ci INIT_LIST_HEAD(&r->res_grantqueue); 42262306a36Sopenharmony_ci INIT_LIST_HEAD(&r->res_convertqueue); 42362306a36Sopenharmony_ci INIT_LIST_HEAD(&r->res_waitqueue); 42462306a36Sopenharmony_ci INIT_LIST_HEAD(&r->res_root_list); 42562306a36Sopenharmony_ci INIT_LIST_HEAD(&r->res_recover_list); 42662306a36Sopenharmony_ci 42762306a36Sopenharmony_ci *r_ret = r; 42862306a36Sopenharmony_ci return 0; 42962306a36Sopenharmony_ci} 43062306a36Sopenharmony_ci 43162306a36Sopenharmony_cistatic int rsb_cmp(struct dlm_rsb *r, const char *name, int nlen) 43262306a36Sopenharmony_ci{ 43362306a36Sopenharmony_ci char maxname[DLM_RESNAME_MAXLEN]; 43462306a36Sopenharmony_ci 43562306a36Sopenharmony_ci memset(maxname, 0, DLM_RESNAME_MAXLEN); 43662306a36Sopenharmony_ci memcpy(maxname, name, nlen); 43762306a36Sopenharmony_ci return memcmp(r->res_name, maxname, DLM_RESNAME_MAXLEN); 43862306a36Sopenharmony_ci} 43962306a36Sopenharmony_ci 44062306a36Sopenharmony_ciint dlm_search_rsb_tree(struct rb_root *tree, const void *name, int len, 44162306a36Sopenharmony_ci struct dlm_rsb **r_ret) 44262306a36Sopenharmony_ci{ 44362306a36Sopenharmony_ci struct rb_node *node = tree->rb_node; 44462306a36Sopenharmony_ci struct dlm_rsb *r; 44562306a36Sopenharmony_ci int rc; 44662306a36Sopenharmony_ci 44762306a36Sopenharmony_ci while (node) { 44862306a36Sopenharmony_ci r = rb_entry(node, struct dlm_rsb, res_hashnode); 44962306a36Sopenharmony_ci rc = rsb_cmp(r, name, len); 45062306a36Sopenharmony_ci if (rc < 0) 45162306a36Sopenharmony_ci node = node->rb_left; 45262306a36Sopenharmony_ci else if (rc > 0) 45362306a36Sopenharmony_ci node = node->rb_right; 45462306a36Sopenharmony_ci else 45562306a36Sopenharmony_ci goto found; 45662306a36Sopenharmony_ci } 45762306a36Sopenharmony_ci *r_ret = NULL; 45862306a36Sopenharmony_ci return -EBADR; 45962306a36Sopenharmony_ci 46062306a36Sopenharmony_ci found: 46162306a36Sopenharmony_ci *r_ret = r; 46262306a36Sopenharmony_ci return 0; 46362306a36Sopenharmony_ci} 46462306a36Sopenharmony_ci 46562306a36Sopenharmony_cistatic int rsb_insert(struct dlm_rsb *rsb, struct rb_root *tree) 46662306a36Sopenharmony_ci{ 46762306a36Sopenharmony_ci struct rb_node **newn = &tree->rb_node; 46862306a36Sopenharmony_ci struct rb_node *parent = NULL; 46962306a36Sopenharmony_ci int rc; 47062306a36Sopenharmony_ci 47162306a36Sopenharmony_ci while (*newn) { 47262306a36Sopenharmony_ci struct dlm_rsb *cur = rb_entry(*newn, struct dlm_rsb, 47362306a36Sopenharmony_ci res_hashnode); 47462306a36Sopenharmony_ci 47562306a36Sopenharmony_ci parent = *newn; 47662306a36Sopenharmony_ci rc = rsb_cmp(cur, rsb->res_name, rsb->res_length); 47762306a36Sopenharmony_ci if (rc < 0) 47862306a36Sopenharmony_ci newn = &parent->rb_left; 47962306a36Sopenharmony_ci else if (rc > 0) 48062306a36Sopenharmony_ci newn = &parent->rb_right; 48162306a36Sopenharmony_ci else { 48262306a36Sopenharmony_ci log_print("rsb_insert match"); 48362306a36Sopenharmony_ci dlm_dump_rsb(rsb); 48462306a36Sopenharmony_ci dlm_dump_rsb(cur); 48562306a36Sopenharmony_ci return -EEXIST; 48662306a36Sopenharmony_ci } 48762306a36Sopenharmony_ci } 48862306a36Sopenharmony_ci 48962306a36Sopenharmony_ci rb_link_node(&rsb->res_hashnode, parent, newn); 49062306a36Sopenharmony_ci rb_insert_color(&rsb->res_hashnode, tree); 49162306a36Sopenharmony_ci return 0; 49262306a36Sopenharmony_ci} 49362306a36Sopenharmony_ci 49462306a36Sopenharmony_ci/* 49562306a36Sopenharmony_ci * Find rsb in rsbtbl and potentially create/add one 49662306a36Sopenharmony_ci * 49762306a36Sopenharmony_ci * Delaying the release of rsb's has a similar benefit to applications keeping 49862306a36Sopenharmony_ci * NL locks on an rsb, but without the guarantee that the cached master value 49962306a36Sopenharmony_ci * will still be valid when the rsb is reused. Apps aren't always smart enough 50062306a36Sopenharmony_ci * to keep NL locks on an rsb that they may lock again shortly; this can lead 50162306a36Sopenharmony_ci * to excessive master lookups and removals if we don't delay the release. 50262306a36Sopenharmony_ci * 50362306a36Sopenharmony_ci * Searching for an rsb means looking through both the normal list and toss 50462306a36Sopenharmony_ci * list. When found on the toss list the rsb is moved to the normal list with 50562306a36Sopenharmony_ci * ref count of 1; when found on normal list the ref count is incremented. 50662306a36Sopenharmony_ci * 50762306a36Sopenharmony_ci * rsb's on the keep list are being used locally and refcounted. 50862306a36Sopenharmony_ci * rsb's on the toss list are not being used locally, and are not refcounted. 50962306a36Sopenharmony_ci * 51062306a36Sopenharmony_ci * The toss list rsb's were either 51162306a36Sopenharmony_ci * - previously used locally but not any more (were on keep list, then 51262306a36Sopenharmony_ci * moved to toss list when last refcount dropped) 51362306a36Sopenharmony_ci * - created and put on toss list as a directory record for a lookup 51462306a36Sopenharmony_ci * (we are the dir node for the res, but are not using the res right now, 51562306a36Sopenharmony_ci * but some other node is) 51662306a36Sopenharmony_ci * 51762306a36Sopenharmony_ci * The purpose of find_rsb() is to return a refcounted rsb for local use. 51862306a36Sopenharmony_ci * So, if the given rsb is on the toss list, it is moved to the keep list 51962306a36Sopenharmony_ci * before being returned. 52062306a36Sopenharmony_ci * 52162306a36Sopenharmony_ci * toss_rsb() happens when all local usage of the rsb is done, i.e. no 52262306a36Sopenharmony_ci * more refcounts exist, so the rsb is moved from the keep list to the 52362306a36Sopenharmony_ci * toss list. 52462306a36Sopenharmony_ci * 52562306a36Sopenharmony_ci * rsb's on both keep and toss lists are used for doing a name to master 52662306a36Sopenharmony_ci * lookups. rsb's that are in use locally (and being refcounted) are on 52762306a36Sopenharmony_ci * the keep list, rsb's that are not in use locally (not refcounted) and 52862306a36Sopenharmony_ci * only exist for name/master lookups are on the toss list. 52962306a36Sopenharmony_ci * 53062306a36Sopenharmony_ci * rsb's on the toss list who's dir_nodeid is not local can have stale 53162306a36Sopenharmony_ci * name/master mappings. So, remote requests on such rsb's can potentially 53262306a36Sopenharmony_ci * return with an error, which means the mapping is stale and needs to 53362306a36Sopenharmony_ci * be updated with a new lookup. (The idea behind MASTER UNCERTAIN and 53462306a36Sopenharmony_ci * first_lkid is to keep only a single outstanding request on an rsb 53562306a36Sopenharmony_ci * while that rsb has a potentially stale master.) 53662306a36Sopenharmony_ci */ 53762306a36Sopenharmony_ci 53862306a36Sopenharmony_cistatic int find_rsb_dir(struct dlm_ls *ls, const void *name, int len, 53962306a36Sopenharmony_ci uint32_t hash, uint32_t b, 54062306a36Sopenharmony_ci int dir_nodeid, int from_nodeid, 54162306a36Sopenharmony_ci unsigned int flags, struct dlm_rsb **r_ret) 54262306a36Sopenharmony_ci{ 54362306a36Sopenharmony_ci struct dlm_rsb *r = NULL; 54462306a36Sopenharmony_ci int our_nodeid = dlm_our_nodeid(); 54562306a36Sopenharmony_ci int from_local = 0; 54662306a36Sopenharmony_ci int from_other = 0; 54762306a36Sopenharmony_ci int from_dir = 0; 54862306a36Sopenharmony_ci int create = 0; 54962306a36Sopenharmony_ci int error; 55062306a36Sopenharmony_ci 55162306a36Sopenharmony_ci if (flags & R_RECEIVE_REQUEST) { 55262306a36Sopenharmony_ci if (from_nodeid == dir_nodeid) 55362306a36Sopenharmony_ci from_dir = 1; 55462306a36Sopenharmony_ci else 55562306a36Sopenharmony_ci from_other = 1; 55662306a36Sopenharmony_ci } else if (flags & R_REQUEST) { 55762306a36Sopenharmony_ci from_local = 1; 55862306a36Sopenharmony_ci } 55962306a36Sopenharmony_ci 56062306a36Sopenharmony_ci /* 56162306a36Sopenharmony_ci * flags & R_RECEIVE_RECOVER is from dlm_recover_master_copy, so 56262306a36Sopenharmony_ci * from_nodeid has sent us a lock in dlm_recover_locks, believing 56362306a36Sopenharmony_ci * we're the new master. Our local recovery may not have set 56462306a36Sopenharmony_ci * res_master_nodeid to our_nodeid yet, so allow either. Don't 56562306a36Sopenharmony_ci * create the rsb; dlm_recover_process_copy() will handle EBADR 56662306a36Sopenharmony_ci * by resending. 56762306a36Sopenharmony_ci * 56862306a36Sopenharmony_ci * If someone sends us a request, we are the dir node, and we do 56962306a36Sopenharmony_ci * not find the rsb anywhere, then recreate it. This happens if 57062306a36Sopenharmony_ci * someone sends us a request after we have removed/freed an rsb 57162306a36Sopenharmony_ci * from our toss list. (They sent a request instead of lookup 57262306a36Sopenharmony_ci * because they are using an rsb from their toss list.) 57362306a36Sopenharmony_ci */ 57462306a36Sopenharmony_ci 57562306a36Sopenharmony_ci if (from_local || from_dir || 57662306a36Sopenharmony_ci (from_other && (dir_nodeid == our_nodeid))) { 57762306a36Sopenharmony_ci create = 1; 57862306a36Sopenharmony_ci } 57962306a36Sopenharmony_ci 58062306a36Sopenharmony_ci retry: 58162306a36Sopenharmony_ci if (create) { 58262306a36Sopenharmony_ci error = pre_rsb_struct(ls); 58362306a36Sopenharmony_ci if (error < 0) 58462306a36Sopenharmony_ci goto out; 58562306a36Sopenharmony_ci } 58662306a36Sopenharmony_ci 58762306a36Sopenharmony_ci spin_lock(&ls->ls_rsbtbl[b].lock); 58862306a36Sopenharmony_ci 58962306a36Sopenharmony_ci error = dlm_search_rsb_tree(&ls->ls_rsbtbl[b].keep, name, len, &r); 59062306a36Sopenharmony_ci if (error) 59162306a36Sopenharmony_ci goto do_toss; 59262306a36Sopenharmony_ci 59362306a36Sopenharmony_ci /* 59462306a36Sopenharmony_ci * rsb is active, so we can't check master_nodeid without lock_rsb. 59562306a36Sopenharmony_ci */ 59662306a36Sopenharmony_ci 59762306a36Sopenharmony_ci kref_get(&r->res_ref); 59862306a36Sopenharmony_ci goto out_unlock; 59962306a36Sopenharmony_ci 60062306a36Sopenharmony_ci 60162306a36Sopenharmony_ci do_toss: 60262306a36Sopenharmony_ci error = dlm_search_rsb_tree(&ls->ls_rsbtbl[b].toss, name, len, &r); 60362306a36Sopenharmony_ci if (error) 60462306a36Sopenharmony_ci goto do_new; 60562306a36Sopenharmony_ci 60662306a36Sopenharmony_ci /* 60762306a36Sopenharmony_ci * rsb found inactive (master_nodeid may be out of date unless 60862306a36Sopenharmony_ci * we are the dir_nodeid or were the master) No other thread 60962306a36Sopenharmony_ci * is using this rsb because it's on the toss list, so we can 61062306a36Sopenharmony_ci * look at or update res_master_nodeid without lock_rsb. 61162306a36Sopenharmony_ci */ 61262306a36Sopenharmony_ci 61362306a36Sopenharmony_ci if ((r->res_master_nodeid != our_nodeid) && from_other) { 61462306a36Sopenharmony_ci /* our rsb was not master, and another node (not the dir node) 61562306a36Sopenharmony_ci has sent us a request */ 61662306a36Sopenharmony_ci log_debug(ls, "find_rsb toss from_other %d master %d dir %d %s", 61762306a36Sopenharmony_ci from_nodeid, r->res_master_nodeid, dir_nodeid, 61862306a36Sopenharmony_ci r->res_name); 61962306a36Sopenharmony_ci error = -ENOTBLK; 62062306a36Sopenharmony_ci goto out_unlock; 62162306a36Sopenharmony_ci } 62262306a36Sopenharmony_ci 62362306a36Sopenharmony_ci if ((r->res_master_nodeid != our_nodeid) && from_dir) { 62462306a36Sopenharmony_ci /* don't think this should ever happen */ 62562306a36Sopenharmony_ci log_error(ls, "find_rsb toss from_dir %d master %d", 62662306a36Sopenharmony_ci from_nodeid, r->res_master_nodeid); 62762306a36Sopenharmony_ci dlm_print_rsb(r); 62862306a36Sopenharmony_ci /* fix it and go on */ 62962306a36Sopenharmony_ci r->res_master_nodeid = our_nodeid; 63062306a36Sopenharmony_ci r->res_nodeid = 0; 63162306a36Sopenharmony_ci rsb_clear_flag(r, RSB_MASTER_UNCERTAIN); 63262306a36Sopenharmony_ci r->res_first_lkid = 0; 63362306a36Sopenharmony_ci } 63462306a36Sopenharmony_ci 63562306a36Sopenharmony_ci if (from_local && (r->res_master_nodeid != our_nodeid)) { 63662306a36Sopenharmony_ci /* Because we have held no locks on this rsb, 63762306a36Sopenharmony_ci res_master_nodeid could have become stale. */ 63862306a36Sopenharmony_ci rsb_set_flag(r, RSB_MASTER_UNCERTAIN); 63962306a36Sopenharmony_ci r->res_first_lkid = 0; 64062306a36Sopenharmony_ci } 64162306a36Sopenharmony_ci 64262306a36Sopenharmony_ci rb_erase(&r->res_hashnode, &ls->ls_rsbtbl[b].toss); 64362306a36Sopenharmony_ci error = rsb_insert(r, &ls->ls_rsbtbl[b].keep); 64462306a36Sopenharmony_ci goto out_unlock; 64562306a36Sopenharmony_ci 64662306a36Sopenharmony_ci 64762306a36Sopenharmony_ci do_new: 64862306a36Sopenharmony_ci /* 64962306a36Sopenharmony_ci * rsb not found 65062306a36Sopenharmony_ci */ 65162306a36Sopenharmony_ci 65262306a36Sopenharmony_ci if (error == -EBADR && !create) 65362306a36Sopenharmony_ci goto out_unlock; 65462306a36Sopenharmony_ci 65562306a36Sopenharmony_ci error = get_rsb_struct(ls, name, len, &r); 65662306a36Sopenharmony_ci if (error == -EAGAIN) { 65762306a36Sopenharmony_ci spin_unlock(&ls->ls_rsbtbl[b].lock); 65862306a36Sopenharmony_ci goto retry; 65962306a36Sopenharmony_ci } 66062306a36Sopenharmony_ci if (error) 66162306a36Sopenharmony_ci goto out_unlock; 66262306a36Sopenharmony_ci 66362306a36Sopenharmony_ci r->res_hash = hash; 66462306a36Sopenharmony_ci r->res_bucket = b; 66562306a36Sopenharmony_ci r->res_dir_nodeid = dir_nodeid; 66662306a36Sopenharmony_ci kref_init(&r->res_ref); 66762306a36Sopenharmony_ci 66862306a36Sopenharmony_ci if (from_dir) { 66962306a36Sopenharmony_ci /* want to see how often this happens */ 67062306a36Sopenharmony_ci log_debug(ls, "find_rsb new from_dir %d recreate %s", 67162306a36Sopenharmony_ci from_nodeid, r->res_name); 67262306a36Sopenharmony_ci r->res_master_nodeid = our_nodeid; 67362306a36Sopenharmony_ci r->res_nodeid = 0; 67462306a36Sopenharmony_ci goto out_add; 67562306a36Sopenharmony_ci } 67662306a36Sopenharmony_ci 67762306a36Sopenharmony_ci if (from_other && (dir_nodeid != our_nodeid)) { 67862306a36Sopenharmony_ci /* should never happen */ 67962306a36Sopenharmony_ci log_error(ls, "find_rsb new from_other %d dir %d our %d %s", 68062306a36Sopenharmony_ci from_nodeid, dir_nodeid, our_nodeid, r->res_name); 68162306a36Sopenharmony_ci dlm_free_rsb(r); 68262306a36Sopenharmony_ci r = NULL; 68362306a36Sopenharmony_ci error = -ENOTBLK; 68462306a36Sopenharmony_ci goto out_unlock; 68562306a36Sopenharmony_ci } 68662306a36Sopenharmony_ci 68762306a36Sopenharmony_ci if (from_other) { 68862306a36Sopenharmony_ci log_debug(ls, "find_rsb new from_other %d dir %d %s", 68962306a36Sopenharmony_ci from_nodeid, dir_nodeid, r->res_name); 69062306a36Sopenharmony_ci } 69162306a36Sopenharmony_ci 69262306a36Sopenharmony_ci if (dir_nodeid == our_nodeid) { 69362306a36Sopenharmony_ci /* When we are the dir nodeid, we can set the master 69462306a36Sopenharmony_ci node immediately */ 69562306a36Sopenharmony_ci r->res_master_nodeid = our_nodeid; 69662306a36Sopenharmony_ci r->res_nodeid = 0; 69762306a36Sopenharmony_ci } else { 69862306a36Sopenharmony_ci /* set_master will send_lookup to dir_nodeid */ 69962306a36Sopenharmony_ci r->res_master_nodeid = 0; 70062306a36Sopenharmony_ci r->res_nodeid = -1; 70162306a36Sopenharmony_ci } 70262306a36Sopenharmony_ci 70362306a36Sopenharmony_ci out_add: 70462306a36Sopenharmony_ci error = rsb_insert(r, &ls->ls_rsbtbl[b].keep); 70562306a36Sopenharmony_ci out_unlock: 70662306a36Sopenharmony_ci spin_unlock(&ls->ls_rsbtbl[b].lock); 70762306a36Sopenharmony_ci out: 70862306a36Sopenharmony_ci *r_ret = r; 70962306a36Sopenharmony_ci return error; 71062306a36Sopenharmony_ci} 71162306a36Sopenharmony_ci 71262306a36Sopenharmony_ci/* During recovery, other nodes can send us new MSTCPY locks (from 71362306a36Sopenharmony_ci dlm_recover_locks) before we've made ourself master (in 71462306a36Sopenharmony_ci dlm_recover_masters). */ 71562306a36Sopenharmony_ci 71662306a36Sopenharmony_cistatic int find_rsb_nodir(struct dlm_ls *ls, const void *name, int len, 71762306a36Sopenharmony_ci uint32_t hash, uint32_t b, 71862306a36Sopenharmony_ci int dir_nodeid, int from_nodeid, 71962306a36Sopenharmony_ci unsigned int flags, struct dlm_rsb **r_ret) 72062306a36Sopenharmony_ci{ 72162306a36Sopenharmony_ci struct dlm_rsb *r = NULL; 72262306a36Sopenharmony_ci int our_nodeid = dlm_our_nodeid(); 72362306a36Sopenharmony_ci int recover = (flags & R_RECEIVE_RECOVER); 72462306a36Sopenharmony_ci int error; 72562306a36Sopenharmony_ci 72662306a36Sopenharmony_ci retry: 72762306a36Sopenharmony_ci error = pre_rsb_struct(ls); 72862306a36Sopenharmony_ci if (error < 0) 72962306a36Sopenharmony_ci goto out; 73062306a36Sopenharmony_ci 73162306a36Sopenharmony_ci spin_lock(&ls->ls_rsbtbl[b].lock); 73262306a36Sopenharmony_ci 73362306a36Sopenharmony_ci error = dlm_search_rsb_tree(&ls->ls_rsbtbl[b].keep, name, len, &r); 73462306a36Sopenharmony_ci if (error) 73562306a36Sopenharmony_ci goto do_toss; 73662306a36Sopenharmony_ci 73762306a36Sopenharmony_ci /* 73862306a36Sopenharmony_ci * rsb is active, so we can't check master_nodeid without lock_rsb. 73962306a36Sopenharmony_ci */ 74062306a36Sopenharmony_ci 74162306a36Sopenharmony_ci kref_get(&r->res_ref); 74262306a36Sopenharmony_ci goto out_unlock; 74362306a36Sopenharmony_ci 74462306a36Sopenharmony_ci 74562306a36Sopenharmony_ci do_toss: 74662306a36Sopenharmony_ci error = dlm_search_rsb_tree(&ls->ls_rsbtbl[b].toss, name, len, &r); 74762306a36Sopenharmony_ci if (error) 74862306a36Sopenharmony_ci goto do_new; 74962306a36Sopenharmony_ci 75062306a36Sopenharmony_ci /* 75162306a36Sopenharmony_ci * rsb found inactive. No other thread is using this rsb because 75262306a36Sopenharmony_ci * it's on the toss list, so we can look at or update 75362306a36Sopenharmony_ci * res_master_nodeid without lock_rsb. 75462306a36Sopenharmony_ci */ 75562306a36Sopenharmony_ci 75662306a36Sopenharmony_ci if (!recover && (r->res_master_nodeid != our_nodeid) && from_nodeid) { 75762306a36Sopenharmony_ci /* our rsb is not master, and another node has sent us a 75862306a36Sopenharmony_ci request; this should never happen */ 75962306a36Sopenharmony_ci log_error(ls, "find_rsb toss from_nodeid %d master %d dir %d", 76062306a36Sopenharmony_ci from_nodeid, r->res_master_nodeid, dir_nodeid); 76162306a36Sopenharmony_ci dlm_print_rsb(r); 76262306a36Sopenharmony_ci error = -ENOTBLK; 76362306a36Sopenharmony_ci goto out_unlock; 76462306a36Sopenharmony_ci } 76562306a36Sopenharmony_ci 76662306a36Sopenharmony_ci if (!recover && (r->res_master_nodeid != our_nodeid) && 76762306a36Sopenharmony_ci (dir_nodeid == our_nodeid)) { 76862306a36Sopenharmony_ci /* our rsb is not master, and we are dir; may as well fix it; 76962306a36Sopenharmony_ci this should never happen */ 77062306a36Sopenharmony_ci log_error(ls, "find_rsb toss our %d master %d dir %d", 77162306a36Sopenharmony_ci our_nodeid, r->res_master_nodeid, dir_nodeid); 77262306a36Sopenharmony_ci dlm_print_rsb(r); 77362306a36Sopenharmony_ci r->res_master_nodeid = our_nodeid; 77462306a36Sopenharmony_ci r->res_nodeid = 0; 77562306a36Sopenharmony_ci } 77662306a36Sopenharmony_ci 77762306a36Sopenharmony_ci rb_erase(&r->res_hashnode, &ls->ls_rsbtbl[b].toss); 77862306a36Sopenharmony_ci error = rsb_insert(r, &ls->ls_rsbtbl[b].keep); 77962306a36Sopenharmony_ci goto out_unlock; 78062306a36Sopenharmony_ci 78162306a36Sopenharmony_ci 78262306a36Sopenharmony_ci do_new: 78362306a36Sopenharmony_ci /* 78462306a36Sopenharmony_ci * rsb not found 78562306a36Sopenharmony_ci */ 78662306a36Sopenharmony_ci 78762306a36Sopenharmony_ci error = get_rsb_struct(ls, name, len, &r); 78862306a36Sopenharmony_ci if (error == -EAGAIN) { 78962306a36Sopenharmony_ci spin_unlock(&ls->ls_rsbtbl[b].lock); 79062306a36Sopenharmony_ci goto retry; 79162306a36Sopenharmony_ci } 79262306a36Sopenharmony_ci if (error) 79362306a36Sopenharmony_ci goto out_unlock; 79462306a36Sopenharmony_ci 79562306a36Sopenharmony_ci r->res_hash = hash; 79662306a36Sopenharmony_ci r->res_bucket = b; 79762306a36Sopenharmony_ci r->res_dir_nodeid = dir_nodeid; 79862306a36Sopenharmony_ci r->res_master_nodeid = dir_nodeid; 79962306a36Sopenharmony_ci r->res_nodeid = (dir_nodeid == our_nodeid) ? 0 : dir_nodeid; 80062306a36Sopenharmony_ci kref_init(&r->res_ref); 80162306a36Sopenharmony_ci 80262306a36Sopenharmony_ci error = rsb_insert(r, &ls->ls_rsbtbl[b].keep); 80362306a36Sopenharmony_ci out_unlock: 80462306a36Sopenharmony_ci spin_unlock(&ls->ls_rsbtbl[b].lock); 80562306a36Sopenharmony_ci out: 80662306a36Sopenharmony_ci *r_ret = r; 80762306a36Sopenharmony_ci return error; 80862306a36Sopenharmony_ci} 80962306a36Sopenharmony_ci 81062306a36Sopenharmony_cistatic int find_rsb(struct dlm_ls *ls, const void *name, int len, 81162306a36Sopenharmony_ci int from_nodeid, unsigned int flags, 81262306a36Sopenharmony_ci struct dlm_rsb **r_ret) 81362306a36Sopenharmony_ci{ 81462306a36Sopenharmony_ci uint32_t hash, b; 81562306a36Sopenharmony_ci int dir_nodeid; 81662306a36Sopenharmony_ci 81762306a36Sopenharmony_ci if (len > DLM_RESNAME_MAXLEN) 81862306a36Sopenharmony_ci return -EINVAL; 81962306a36Sopenharmony_ci 82062306a36Sopenharmony_ci hash = jhash(name, len, 0); 82162306a36Sopenharmony_ci b = hash & (ls->ls_rsbtbl_size - 1); 82262306a36Sopenharmony_ci 82362306a36Sopenharmony_ci dir_nodeid = dlm_hash2nodeid(ls, hash); 82462306a36Sopenharmony_ci 82562306a36Sopenharmony_ci if (dlm_no_directory(ls)) 82662306a36Sopenharmony_ci return find_rsb_nodir(ls, name, len, hash, b, dir_nodeid, 82762306a36Sopenharmony_ci from_nodeid, flags, r_ret); 82862306a36Sopenharmony_ci else 82962306a36Sopenharmony_ci return find_rsb_dir(ls, name, len, hash, b, dir_nodeid, 83062306a36Sopenharmony_ci from_nodeid, flags, r_ret); 83162306a36Sopenharmony_ci} 83262306a36Sopenharmony_ci 83362306a36Sopenharmony_ci/* we have received a request and found that res_master_nodeid != our_nodeid, 83462306a36Sopenharmony_ci so we need to return an error or make ourself the master */ 83562306a36Sopenharmony_ci 83662306a36Sopenharmony_cistatic int validate_master_nodeid(struct dlm_ls *ls, struct dlm_rsb *r, 83762306a36Sopenharmony_ci int from_nodeid) 83862306a36Sopenharmony_ci{ 83962306a36Sopenharmony_ci if (dlm_no_directory(ls)) { 84062306a36Sopenharmony_ci log_error(ls, "find_rsb keep from_nodeid %d master %d dir %d", 84162306a36Sopenharmony_ci from_nodeid, r->res_master_nodeid, 84262306a36Sopenharmony_ci r->res_dir_nodeid); 84362306a36Sopenharmony_ci dlm_print_rsb(r); 84462306a36Sopenharmony_ci return -ENOTBLK; 84562306a36Sopenharmony_ci } 84662306a36Sopenharmony_ci 84762306a36Sopenharmony_ci if (from_nodeid != r->res_dir_nodeid) { 84862306a36Sopenharmony_ci /* our rsb is not master, and another node (not the dir node) 84962306a36Sopenharmony_ci has sent us a request. this is much more common when our 85062306a36Sopenharmony_ci master_nodeid is zero, so limit debug to non-zero. */ 85162306a36Sopenharmony_ci 85262306a36Sopenharmony_ci if (r->res_master_nodeid) { 85362306a36Sopenharmony_ci log_debug(ls, "validate master from_other %d master %d " 85462306a36Sopenharmony_ci "dir %d first %x %s", from_nodeid, 85562306a36Sopenharmony_ci r->res_master_nodeid, r->res_dir_nodeid, 85662306a36Sopenharmony_ci r->res_first_lkid, r->res_name); 85762306a36Sopenharmony_ci } 85862306a36Sopenharmony_ci return -ENOTBLK; 85962306a36Sopenharmony_ci } else { 86062306a36Sopenharmony_ci /* our rsb is not master, but the dir nodeid has sent us a 86162306a36Sopenharmony_ci request; this could happen with master 0 / res_nodeid -1 */ 86262306a36Sopenharmony_ci 86362306a36Sopenharmony_ci if (r->res_master_nodeid) { 86462306a36Sopenharmony_ci log_error(ls, "validate master from_dir %d master %d " 86562306a36Sopenharmony_ci "first %x %s", 86662306a36Sopenharmony_ci from_nodeid, r->res_master_nodeid, 86762306a36Sopenharmony_ci r->res_first_lkid, r->res_name); 86862306a36Sopenharmony_ci } 86962306a36Sopenharmony_ci 87062306a36Sopenharmony_ci r->res_master_nodeid = dlm_our_nodeid(); 87162306a36Sopenharmony_ci r->res_nodeid = 0; 87262306a36Sopenharmony_ci return 0; 87362306a36Sopenharmony_ci } 87462306a36Sopenharmony_ci} 87562306a36Sopenharmony_ci 87662306a36Sopenharmony_cistatic void __dlm_master_lookup(struct dlm_ls *ls, struct dlm_rsb *r, int our_nodeid, 87762306a36Sopenharmony_ci int from_nodeid, bool toss_list, unsigned int flags, 87862306a36Sopenharmony_ci int *r_nodeid, int *result) 87962306a36Sopenharmony_ci{ 88062306a36Sopenharmony_ci int fix_master = (flags & DLM_LU_RECOVER_MASTER); 88162306a36Sopenharmony_ci int from_master = (flags & DLM_LU_RECOVER_DIR); 88262306a36Sopenharmony_ci 88362306a36Sopenharmony_ci if (r->res_dir_nodeid != our_nodeid) { 88462306a36Sopenharmony_ci /* should not happen, but may as well fix it and carry on */ 88562306a36Sopenharmony_ci log_error(ls, "%s res_dir %d our %d %s", __func__, 88662306a36Sopenharmony_ci r->res_dir_nodeid, our_nodeid, r->res_name); 88762306a36Sopenharmony_ci r->res_dir_nodeid = our_nodeid; 88862306a36Sopenharmony_ci } 88962306a36Sopenharmony_ci 89062306a36Sopenharmony_ci if (fix_master && dlm_is_removed(ls, r->res_master_nodeid)) { 89162306a36Sopenharmony_ci /* Recovery uses this function to set a new master when 89262306a36Sopenharmony_ci * the previous master failed. Setting NEW_MASTER will 89362306a36Sopenharmony_ci * force dlm_recover_masters to call recover_master on this 89462306a36Sopenharmony_ci * rsb even though the res_nodeid is no longer removed. 89562306a36Sopenharmony_ci */ 89662306a36Sopenharmony_ci 89762306a36Sopenharmony_ci r->res_master_nodeid = from_nodeid; 89862306a36Sopenharmony_ci r->res_nodeid = from_nodeid; 89962306a36Sopenharmony_ci rsb_set_flag(r, RSB_NEW_MASTER); 90062306a36Sopenharmony_ci 90162306a36Sopenharmony_ci if (toss_list) { 90262306a36Sopenharmony_ci /* I don't think we should ever find it on toss list. */ 90362306a36Sopenharmony_ci log_error(ls, "%s fix_master on toss", __func__); 90462306a36Sopenharmony_ci dlm_dump_rsb(r); 90562306a36Sopenharmony_ci } 90662306a36Sopenharmony_ci } 90762306a36Sopenharmony_ci 90862306a36Sopenharmony_ci if (from_master && (r->res_master_nodeid != from_nodeid)) { 90962306a36Sopenharmony_ci /* this will happen if from_nodeid became master during 91062306a36Sopenharmony_ci * a previous recovery cycle, and we aborted the previous 91162306a36Sopenharmony_ci * cycle before recovering this master value 91262306a36Sopenharmony_ci */ 91362306a36Sopenharmony_ci 91462306a36Sopenharmony_ci log_limit(ls, "%s from_master %d master_nodeid %d res_nodeid %d first %x %s", 91562306a36Sopenharmony_ci __func__, from_nodeid, r->res_master_nodeid, 91662306a36Sopenharmony_ci r->res_nodeid, r->res_first_lkid, r->res_name); 91762306a36Sopenharmony_ci 91862306a36Sopenharmony_ci if (r->res_master_nodeid == our_nodeid) { 91962306a36Sopenharmony_ci log_error(ls, "from_master %d our_master", from_nodeid); 92062306a36Sopenharmony_ci dlm_dump_rsb(r); 92162306a36Sopenharmony_ci goto ret_assign; 92262306a36Sopenharmony_ci } 92362306a36Sopenharmony_ci 92462306a36Sopenharmony_ci r->res_master_nodeid = from_nodeid; 92562306a36Sopenharmony_ci r->res_nodeid = from_nodeid; 92662306a36Sopenharmony_ci rsb_set_flag(r, RSB_NEW_MASTER); 92762306a36Sopenharmony_ci } 92862306a36Sopenharmony_ci 92962306a36Sopenharmony_ci if (!r->res_master_nodeid) { 93062306a36Sopenharmony_ci /* this will happen if recovery happens while we're looking 93162306a36Sopenharmony_ci * up the master for this rsb 93262306a36Sopenharmony_ci */ 93362306a36Sopenharmony_ci 93462306a36Sopenharmony_ci log_debug(ls, "%s master 0 to %d first %x %s", __func__, 93562306a36Sopenharmony_ci from_nodeid, r->res_first_lkid, r->res_name); 93662306a36Sopenharmony_ci r->res_master_nodeid = from_nodeid; 93762306a36Sopenharmony_ci r->res_nodeid = from_nodeid; 93862306a36Sopenharmony_ci } 93962306a36Sopenharmony_ci 94062306a36Sopenharmony_ci if (!from_master && !fix_master && 94162306a36Sopenharmony_ci (r->res_master_nodeid == from_nodeid)) { 94262306a36Sopenharmony_ci /* this can happen when the master sends remove, the dir node 94362306a36Sopenharmony_ci * finds the rsb on the keep list and ignores the remove, 94462306a36Sopenharmony_ci * and the former master sends a lookup 94562306a36Sopenharmony_ci */ 94662306a36Sopenharmony_ci 94762306a36Sopenharmony_ci log_limit(ls, "%s from master %d flags %x first %x %s", 94862306a36Sopenharmony_ci __func__, from_nodeid, flags, r->res_first_lkid, 94962306a36Sopenharmony_ci r->res_name); 95062306a36Sopenharmony_ci } 95162306a36Sopenharmony_ci 95262306a36Sopenharmony_ci ret_assign: 95362306a36Sopenharmony_ci *r_nodeid = r->res_master_nodeid; 95462306a36Sopenharmony_ci if (result) 95562306a36Sopenharmony_ci *result = DLM_LU_MATCH; 95662306a36Sopenharmony_ci} 95762306a36Sopenharmony_ci 95862306a36Sopenharmony_ci/* 95962306a36Sopenharmony_ci * We're the dir node for this res and another node wants to know the 96062306a36Sopenharmony_ci * master nodeid. During normal operation (non recovery) this is only 96162306a36Sopenharmony_ci * called from receive_lookup(); master lookups when the local node is 96262306a36Sopenharmony_ci * the dir node are done by find_rsb(). 96362306a36Sopenharmony_ci * 96462306a36Sopenharmony_ci * normal operation, we are the dir node for a resource 96562306a36Sopenharmony_ci * . _request_lock 96662306a36Sopenharmony_ci * . set_master 96762306a36Sopenharmony_ci * . send_lookup 96862306a36Sopenharmony_ci * . receive_lookup 96962306a36Sopenharmony_ci * . dlm_master_lookup flags 0 97062306a36Sopenharmony_ci * 97162306a36Sopenharmony_ci * recover directory, we are rebuilding dir for all resources 97262306a36Sopenharmony_ci * . dlm_recover_directory 97362306a36Sopenharmony_ci * . dlm_rcom_names 97462306a36Sopenharmony_ci * remote node sends back the rsb names it is master of and we are dir of 97562306a36Sopenharmony_ci * . dlm_master_lookup RECOVER_DIR (fix_master 0, from_master 1) 97662306a36Sopenharmony_ci * we either create new rsb setting remote node as master, or find existing 97762306a36Sopenharmony_ci * rsb and set master to be the remote node. 97862306a36Sopenharmony_ci * 97962306a36Sopenharmony_ci * recover masters, we are finding the new master for resources 98062306a36Sopenharmony_ci * . dlm_recover_masters 98162306a36Sopenharmony_ci * . recover_master 98262306a36Sopenharmony_ci * . dlm_send_rcom_lookup 98362306a36Sopenharmony_ci * . receive_rcom_lookup 98462306a36Sopenharmony_ci * . dlm_master_lookup RECOVER_MASTER (fix_master 1, from_master 0) 98562306a36Sopenharmony_ci */ 98662306a36Sopenharmony_ci 98762306a36Sopenharmony_ciint dlm_master_lookup(struct dlm_ls *ls, int from_nodeid, const char *name, 98862306a36Sopenharmony_ci int len, unsigned int flags, int *r_nodeid, int *result) 98962306a36Sopenharmony_ci{ 99062306a36Sopenharmony_ci struct dlm_rsb *r = NULL; 99162306a36Sopenharmony_ci uint32_t hash, b; 99262306a36Sopenharmony_ci int our_nodeid = dlm_our_nodeid(); 99362306a36Sopenharmony_ci int dir_nodeid, error; 99462306a36Sopenharmony_ci 99562306a36Sopenharmony_ci if (len > DLM_RESNAME_MAXLEN) 99662306a36Sopenharmony_ci return -EINVAL; 99762306a36Sopenharmony_ci 99862306a36Sopenharmony_ci if (from_nodeid == our_nodeid) { 99962306a36Sopenharmony_ci log_error(ls, "dlm_master_lookup from our_nodeid %d flags %x", 100062306a36Sopenharmony_ci our_nodeid, flags); 100162306a36Sopenharmony_ci return -EINVAL; 100262306a36Sopenharmony_ci } 100362306a36Sopenharmony_ci 100462306a36Sopenharmony_ci hash = jhash(name, len, 0); 100562306a36Sopenharmony_ci b = hash & (ls->ls_rsbtbl_size - 1); 100662306a36Sopenharmony_ci 100762306a36Sopenharmony_ci dir_nodeid = dlm_hash2nodeid(ls, hash); 100862306a36Sopenharmony_ci if (dir_nodeid != our_nodeid) { 100962306a36Sopenharmony_ci log_error(ls, "dlm_master_lookup from %d dir %d our %d h %x %d", 101062306a36Sopenharmony_ci from_nodeid, dir_nodeid, our_nodeid, hash, 101162306a36Sopenharmony_ci ls->ls_num_nodes); 101262306a36Sopenharmony_ci *r_nodeid = -1; 101362306a36Sopenharmony_ci return -EINVAL; 101462306a36Sopenharmony_ci } 101562306a36Sopenharmony_ci 101662306a36Sopenharmony_ci retry: 101762306a36Sopenharmony_ci error = pre_rsb_struct(ls); 101862306a36Sopenharmony_ci if (error < 0) 101962306a36Sopenharmony_ci return error; 102062306a36Sopenharmony_ci 102162306a36Sopenharmony_ci spin_lock(&ls->ls_rsbtbl[b].lock); 102262306a36Sopenharmony_ci error = dlm_search_rsb_tree(&ls->ls_rsbtbl[b].keep, name, len, &r); 102362306a36Sopenharmony_ci if (!error) { 102462306a36Sopenharmony_ci /* because the rsb is active, we need to lock_rsb before 102562306a36Sopenharmony_ci * checking/changing re_master_nodeid 102662306a36Sopenharmony_ci */ 102762306a36Sopenharmony_ci 102862306a36Sopenharmony_ci hold_rsb(r); 102962306a36Sopenharmony_ci spin_unlock(&ls->ls_rsbtbl[b].lock); 103062306a36Sopenharmony_ci lock_rsb(r); 103162306a36Sopenharmony_ci 103262306a36Sopenharmony_ci __dlm_master_lookup(ls, r, our_nodeid, from_nodeid, false, 103362306a36Sopenharmony_ci flags, r_nodeid, result); 103462306a36Sopenharmony_ci 103562306a36Sopenharmony_ci /* the rsb was active */ 103662306a36Sopenharmony_ci unlock_rsb(r); 103762306a36Sopenharmony_ci put_rsb(r); 103862306a36Sopenharmony_ci 103962306a36Sopenharmony_ci return 0; 104062306a36Sopenharmony_ci } 104162306a36Sopenharmony_ci 104262306a36Sopenharmony_ci error = dlm_search_rsb_tree(&ls->ls_rsbtbl[b].toss, name, len, &r); 104362306a36Sopenharmony_ci if (error) 104462306a36Sopenharmony_ci goto not_found; 104562306a36Sopenharmony_ci 104662306a36Sopenharmony_ci /* because the rsb is inactive (on toss list), it's not refcounted 104762306a36Sopenharmony_ci * and lock_rsb is not used, but is protected by the rsbtbl lock 104862306a36Sopenharmony_ci */ 104962306a36Sopenharmony_ci 105062306a36Sopenharmony_ci __dlm_master_lookup(ls, r, our_nodeid, from_nodeid, true, flags, 105162306a36Sopenharmony_ci r_nodeid, result); 105262306a36Sopenharmony_ci 105362306a36Sopenharmony_ci r->res_toss_time = jiffies; 105462306a36Sopenharmony_ci /* the rsb was inactive (on toss list) */ 105562306a36Sopenharmony_ci spin_unlock(&ls->ls_rsbtbl[b].lock); 105662306a36Sopenharmony_ci 105762306a36Sopenharmony_ci return 0; 105862306a36Sopenharmony_ci 105962306a36Sopenharmony_ci not_found: 106062306a36Sopenharmony_ci error = get_rsb_struct(ls, name, len, &r); 106162306a36Sopenharmony_ci if (error == -EAGAIN) { 106262306a36Sopenharmony_ci spin_unlock(&ls->ls_rsbtbl[b].lock); 106362306a36Sopenharmony_ci goto retry; 106462306a36Sopenharmony_ci } 106562306a36Sopenharmony_ci if (error) 106662306a36Sopenharmony_ci goto out_unlock; 106762306a36Sopenharmony_ci 106862306a36Sopenharmony_ci r->res_hash = hash; 106962306a36Sopenharmony_ci r->res_bucket = b; 107062306a36Sopenharmony_ci r->res_dir_nodeid = our_nodeid; 107162306a36Sopenharmony_ci r->res_master_nodeid = from_nodeid; 107262306a36Sopenharmony_ci r->res_nodeid = from_nodeid; 107362306a36Sopenharmony_ci kref_init(&r->res_ref); 107462306a36Sopenharmony_ci r->res_toss_time = jiffies; 107562306a36Sopenharmony_ci 107662306a36Sopenharmony_ci error = rsb_insert(r, &ls->ls_rsbtbl[b].toss); 107762306a36Sopenharmony_ci if (error) { 107862306a36Sopenharmony_ci /* should never happen */ 107962306a36Sopenharmony_ci dlm_free_rsb(r); 108062306a36Sopenharmony_ci spin_unlock(&ls->ls_rsbtbl[b].lock); 108162306a36Sopenharmony_ci goto retry; 108262306a36Sopenharmony_ci } 108362306a36Sopenharmony_ci 108462306a36Sopenharmony_ci if (result) 108562306a36Sopenharmony_ci *result = DLM_LU_ADD; 108662306a36Sopenharmony_ci *r_nodeid = from_nodeid; 108762306a36Sopenharmony_ci out_unlock: 108862306a36Sopenharmony_ci spin_unlock(&ls->ls_rsbtbl[b].lock); 108962306a36Sopenharmony_ci return error; 109062306a36Sopenharmony_ci} 109162306a36Sopenharmony_ci 109262306a36Sopenharmony_cistatic void dlm_dump_rsb_hash(struct dlm_ls *ls, uint32_t hash) 109362306a36Sopenharmony_ci{ 109462306a36Sopenharmony_ci struct rb_node *n; 109562306a36Sopenharmony_ci struct dlm_rsb *r; 109662306a36Sopenharmony_ci int i; 109762306a36Sopenharmony_ci 109862306a36Sopenharmony_ci for (i = 0; i < ls->ls_rsbtbl_size; i++) { 109962306a36Sopenharmony_ci spin_lock(&ls->ls_rsbtbl[i].lock); 110062306a36Sopenharmony_ci for (n = rb_first(&ls->ls_rsbtbl[i].keep); n; n = rb_next(n)) { 110162306a36Sopenharmony_ci r = rb_entry(n, struct dlm_rsb, res_hashnode); 110262306a36Sopenharmony_ci if (r->res_hash == hash) 110362306a36Sopenharmony_ci dlm_dump_rsb(r); 110462306a36Sopenharmony_ci } 110562306a36Sopenharmony_ci spin_unlock(&ls->ls_rsbtbl[i].lock); 110662306a36Sopenharmony_ci } 110762306a36Sopenharmony_ci} 110862306a36Sopenharmony_ci 110962306a36Sopenharmony_civoid dlm_dump_rsb_name(struct dlm_ls *ls, const char *name, int len) 111062306a36Sopenharmony_ci{ 111162306a36Sopenharmony_ci struct dlm_rsb *r = NULL; 111262306a36Sopenharmony_ci uint32_t hash, b; 111362306a36Sopenharmony_ci int error; 111462306a36Sopenharmony_ci 111562306a36Sopenharmony_ci hash = jhash(name, len, 0); 111662306a36Sopenharmony_ci b = hash & (ls->ls_rsbtbl_size - 1); 111762306a36Sopenharmony_ci 111862306a36Sopenharmony_ci spin_lock(&ls->ls_rsbtbl[b].lock); 111962306a36Sopenharmony_ci error = dlm_search_rsb_tree(&ls->ls_rsbtbl[b].keep, name, len, &r); 112062306a36Sopenharmony_ci if (!error) 112162306a36Sopenharmony_ci goto out_dump; 112262306a36Sopenharmony_ci 112362306a36Sopenharmony_ci error = dlm_search_rsb_tree(&ls->ls_rsbtbl[b].toss, name, len, &r); 112462306a36Sopenharmony_ci if (error) 112562306a36Sopenharmony_ci goto out; 112662306a36Sopenharmony_ci out_dump: 112762306a36Sopenharmony_ci dlm_dump_rsb(r); 112862306a36Sopenharmony_ci out: 112962306a36Sopenharmony_ci spin_unlock(&ls->ls_rsbtbl[b].lock); 113062306a36Sopenharmony_ci} 113162306a36Sopenharmony_ci 113262306a36Sopenharmony_cistatic void toss_rsb(struct kref *kref) 113362306a36Sopenharmony_ci{ 113462306a36Sopenharmony_ci struct dlm_rsb *r = container_of(kref, struct dlm_rsb, res_ref); 113562306a36Sopenharmony_ci struct dlm_ls *ls = r->res_ls; 113662306a36Sopenharmony_ci 113762306a36Sopenharmony_ci DLM_ASSERT(list_empty(&r->res_root_list), dlm_print_rsb(r);); 113862306a36Sopenharmony_ci kref_init(&r->res_ref); 113962306a36Sopenharmony_ci rb_erase(&r->res_hashnode, &ls->ls_rsbtbl[r->res_bucket].keep); 114062306a36Sopenharmony_ci rsb_insert(r, &ls->ls_rsbtbl[r->res_bucket].toss); 114162306a36Sopenharmony_ci r->res_toss_time = jiffies; 114262306a36Sopenharmony_ci set_bit(DLM_RTF_SHRINK_BIT, &ls->ls_rsbtbl[r->res_bucket].flags); 114362306a36Sopenharmony_ci if (r->res_lvbptr) { 114462306a36Sopenharmony_ci dlm_free_lvb(r->res_lvbptr); 114562306a36Sopenharmony_ci r->res_lvbptr = NULL; 114662306a36Sopenharmony_ci } 114762306a36Sopenharmony_ci} 114862306a36Sopenharmony_ci 114962306a36Sopenharmony_ci/* See comment for unhold_lkb */ 115062306a36Sopenharmony_ci 115162306a36Sopenharmony_cistatic void unhold_rsb(struct dlm_rsb *r) 115262306a36Sopenharmony_ci{ 115362306a36Sopenharmony_ci int rv; 115462306a36Sopenharmony_ci rv = kref_put(&r->res_ref, toss_rsb); 115562306a36Sopenharmony_ci DLM_ASSERT(!rv, dlm_dump_rsb(r);); 115662306a36Sopenharmony_ci} 115762306a36Sopenharmony_ci 115862306a36Sopenharmony_cistatic void kill_rsb(struct kref *kref) 115962306a36Sopenharmony_ci{ 116062306a36Sopenharmony_ci struct dlm_rsb *r = container_of(kref, struct dlm_rsb, res_ref); 116162306a36Sopenharmony_ci 116262306a36Sopenharmony_ci /* All work is done after the return from kref_put() so we 116362306a36Sopenharmony_ci can release the write_lock before the remove and free. */ 116462306a36Sopenharmony_ci 116562306a36Sopenharmony_ci DLM_ASSERT(list_empty(&r->res_lookup), dlm_dump_rsb(r);); 116662306a36Sopenharmony_ci DLM_ASSERT(list_empty(&r->res_grantqueue), dlm_dump_rsb(r);); 116762306a36Sopenharmony_ci DLM_ASSERT(list_empty(&r->res_convertqueue), dlm_dump_rsb(r);); 116862306a36Sopenharmony_ci DLM_ASSERT(list_empty(&r->res_waitqueue), dlm_dump_rsb(r);); 116962306a36Sopenharmony_ci DLM_ASSERT(list_empty(&r->res_root_list), dlm_dump_rsb(r);); 117062306a36Sopenharmony_ci DLM_ASSERT(list_empty(&r->res_recover_list), dlm_dump_rsb(r);); 117162306a36Sopenharmony_ci} 117262306a36Sopenharmony_ci 117362306a36Sopenharmony_ci/* Attaching/detaching lkb's from rsb's is for rsb reference counting. 117462306a36Sopenharmony_ci The rsb must exist as long as any lkb's for it do. */ 117562306a36Sopenharmony_ci 117662306a36Sopenharmony_cistatic void attach_lkb(struct dlm_rsb *r, struct dlm_lkb *lkb) 117762306a36Sopenharmony_ci{ 117862306a36Sopenharmony_ci hold_rsb(r); 117962306a36Sopenharmony_ci lkb->lkb_resource = r; 118062306a36Sopenharmony_ci} 118162306a36Sopenharmony_ci 118262306a36Sopenharmony_cistatic void detach_lkb(struct dlm_lkb *lkb) 118362306a36Sopenharmony_ci{ 118462306a36Sopenharmony_ci if (lkb->lkb_resource) { 118562306a36Sopenharmony_ci put_rsb(lkb->lkb_resource); 118662306a36Sopenharmony_ci lkb->lkb_resource = NULL; 118762306a36Sopenharmony_ci } 118862306a36Sopenharmony_ci} 118962306a36Sopenharmony_ci 119062306a36Sopenharmony_cistatic int _create_lkb(struct dlm_ls *ls, struct dlm_lkb **lkb_ret, 119162306a36Sopenharmony_ci int start, int end) 119262306a36Sopenharmony_ci{ 119362306a36Sopenharmony_ci struct dlm_lkb *lkb; 119462306a36Sopenharmony_ci int rv; 119562306a36Sopenharmony_ci 119662306a36Sopenharmony_ci lkb = dlm_allocate_lkb(ls); 119762306a36Sopenharmony_ci if (!lkb) 119862306a36Sopenharmony_ci return -ENOMEM; 119962306a36Sopenharmony_ci 120062306a36Sopenharmony_ci lkb->lkb_last_bast_mode = -1; 120162306a36Sopenharmony_ci lkb->lkb_nodeid = -1; 120262306a36Sopenharmony_ci lkb->lkb_grmode = DLM_LOCK_IV; 120362306a36Sopenharmony_ci kref_init(&lkb->lkb_ref); 120462306a36Sopenharmony_ci INIT_LIST_HEAD(&lkb->lkb_ownqueue); 120562306a36Sopenharmony_ci INIT_LIST_HEAD(&lkb->lkb_rsb_lookup); 120662306a36Sopenharmony_ci INIT_LIST_HEAD(&lkb->lkb_cb_list); 120762306a36Sopenharmony_ci INIT_LIST_HEAD(&lkb->lkb_callbacks); 120862306a36Sopenharmony_ci spin_lock_init(&lkb->lkb_cb_lock); 120962306a36Sopenharmony_ci INIT_WORK(&lkb->lkb_cb_work, dlm_callback_work); 121062306a36Sopenharmony_ci 121162306a36Sopenharmony_ci idr_preload(GFP_NOFS); 121262306a36Sopenharmony_ci spin_lock(&ls->ls_lkbidr_spin); 121362306a36Sopenharmony_ci rv = idr_alloc(&ls->ls_lkbidr, lkb, start, end, GFP_NOWAIT); 121462306a36Sopenharmony_ci if (rv >= 0) 121562306a36Sopenharmony_ci lkb->lkb_id = rv; 121662306a36Sopenharmony_ci spin_unlock(&ls->ls_lkbidr_spin); 121762306a36Sopenharmony_ci idr_preload_end(); 121862306a36Sopenharmony_ci 121962306a36Sopenharmony_ci if (rv < 0) { 122062306a36Sopenharmony_ci log_error(ls, "create_lkb idr error %d", rv); 122162306a36Sopenharmony_ci dlm_free_lkb(lkb); 122262306a36Sopenharmony_ci return rv; 122362306a36Sopenharmony_ci } 122462306a36Sopenharmony_ci 122562306a36Sopenharmony_ci *lkb_ret = lkb; 122662306a36Sopenharmony_ci return 0; 122762306a36Sopenharmony_ci} 122862306a36Sopenharmony_ci 122962306a36Sopenharmony_cistatic int create_lkb(struct dlm_ls *ls, struct dlm_lkb **lkb_ret) 123062306a36Sopenharmony_ci{ 123162306a36Sopenharmony_ci return _create_lkb(ls, lkb_ret, 1, 0); 123262306a36Sopenharmony_ci} 123362306a36Sopenharmony_ci 123462306a36Sopenharmony_cistatic int find_lkb(struct dlm_ls *ls, uint32_t lkid, struct dlm_lkb **lkb_ret) 123562306a36Sopenharmony_ci{ 123662306a36Sopenharmony_ci struct dlm_lkb *lkb; 123762306a36Sopenharmony_ci 123862306a36Sopenharmony_ci spin_lock(&ls->ls_lkbidr_spin); 123962306a36Sopenharmony_ci lkb = idr_find(&ls->ls_lkbidr, lkid); 124062306a36Sopenharmony_ci if (lkb) 124162306a36Sopenharmony_ci kref_get(&lkb->lkb_ref); 124262306a36Sopenharmony_ci spin_unlock(&ls->ls_lkbidr_spin); 124362306a36Sopenharmony_ci 124462306a36Sopenharmony_ci *lkb_ret = lkb; 124562306a36Sopenharmony_ci return lkb ? 0 : -ENOENT; 124662306a36Sopenharmony_ci} 124762306a36Sopenharmony_ci 124862306a36Sopenharmony_cistatic void kill_lkb(struct kref *kref) 124962306a36Sopenharmony_ci{ 125062306a36Sopenharmony_ci struct dlm_lkb *lkb = container_of(kref, struct dlm_lkb, lkb_ref); 125162306a36Sopenharmony_ci 125262306a36Sopenharmony_ci /* All work is done after the return from kref_put() so we 125362306a36Sopenharmony_ci can release the write_lock before the detach_lkb */ 125462306a36Sopenharmony_ci 125562306a36Sopenharmony_ci DLM_ASSERT(!lkb->lkb_status, dlm_print_lkb(lkb);); 125662306a36Sopenharmony_ci} 125762306a36Sopenharmony_ci 125862306a36Sopenharmony_ci/* __put_lkb() is used when an lkb may not have an rsb attached to 125962306a36Sopenharmony_ci it so we need to provide the lockspace explicitly */ 126062306a36Sopenharmony_ci 126162306a36Sopenharmony_cistatic int __put_lkb(struct dlm_ls *ls, struct dlm_lkb *lkb) 126262306a36Sopenharmony_ci{ 126362306a36Sopenharmony_ci uint32_t lkid = lkb->lkb_id; 126462306a36Sopenharmony_ci int rv; 126562306a36Sopenharmony_ci 126662306a36Sopenharmony_ci rv = kref_put_lock(&lkb->lkb_ref, kill_lkb, 126762306a36Sopenharmony_ci &ls->ls_lkbidr_spin); 126862306a36Sopenharmony_ci if (rv) { 126962306a36Sopenharmony_ci idr_remove(&ls->ls_lkbidr, lkid); 127062306a36Sopenharmony_ci spin_unlock(&ls->ls_lkbidr_spin); 127162306a36Sopenharmony_ci 127262306a36Sopenharmony_ci detach_lkb(lkb); 127362306a36Sopenharmony_ci 127462306a36Sopenharmony_ci /* for local/process lkbs, lvbptr points to caller's lksb */ 127562306a36Sopenharmony_ci if (lkb->lkb_lvbptr && is_master_copy(lkb)) 127662306a36Sopenharmony_ci dlm_free_lvb(lkb->lkb_lvbptr); 127762306a36Sopenharmony_ci dlm_free_lkb(lkb); 127862306a36Sopenharmony_ci } 127962306a36Sopenharmony_ci 128062306a36Sopenharmony_ci return rv; 128162306a36Sopenharmony_ci} 128262306a36Sopenharmony_ci 128362306a36Sopenharmony_ciint dlm_put_lkb(struct dlm_lkb *lkb) 128462306a36Sopenharmony_ci{ 128562306a36Sopenharmony_ci struct dlm_ls *ls; 128662306a36Sopenharmony_ci 128762306a36Sopenharmony_ci DLM_ASSERT(lkb->lkb_resource, dlm_print_lkb(lkb);); 128862306a36Sopenharmony_ci DLM_ASSERT(lkb->lkb_resource->res_ls, dlm_print_lkb(lkb);); 128962306a36Sopenharmony_ci 129062306a36Sopenharmony_ci ls = lkb->lkb_resource->res_ls; 129162306a36Sopenharmony_ci return __put_lkb(ls, lkb); 129262306a36Sopenharmony_ci} 129362306a36Sopenharmony_ci 129462306a36Sopenharmony_ci/* This is only called to add a reference when the code already holds 129562306a36Sopenharmony_ci a valid reference to the lkb, so there's no need for locking. */ 129662306a36Sopenharmony_ci 129762306a36Sopenharmony_cistatic inline void hold_lkb(struct dlm_lkb *lkb) 129862306a36Sopenharmony_ci{ 129962306a36Sopenharmony_ci kref_get(&lkb->lkb_ref); 130062306a36Sopenharmony_ci} 130162306a36Sopenharmony_ci 130262306a36Sopenharmony_cistatic void unhold_lkb_assert(struct kref *kref) 130362306a36Sopenharmony_ci{ 130462306a36Sopenharmony_ci struct dlm_lkb *lkb = container_of(kref, struct dlm_lkb, lkb_ref); 130562306a36Sopenharmony_ci 130662306a36Sopenharmony_ci DLM_ASSERT(false, dlm_print_lkb(lkb);); 130762306a36Sopenharmony_ci} 130862306a36Sopenharmony_ci 130962306a36Sopenharmony_ci/* This is called when we need to remove a reference and are certain 131062306a36Sopenharmony_ci it's not the last ref. e.g. del_lkb is always called between a 131162306a36Sopenharmony_ci find_lkb/put_lkb and is always the inverse of a previous add_lkb. 131262306a36Sopenharmony_ci put_lkb would work fine, but would involve unnecessary locking */ 131362306a36Sopenharmony_ci 131462306a36Sopenharmony_cistatic inline void unhold_lkb(struct dlm_lkb *lkb) 131562306a36Sopenharmony_ci{ 131662306a36Sopenharmony_ci kref_put(&lkb->lkb_ref, unhold_lkb_assert); 131762306a36Sopenharmony_ci} 131862306a36Sopenharmony_ci 131962306a36Sopenharmony_cistatic void lkb_add_ordered(struct list_head *new, struct list_head *head, 132062306a36Sopenharmony_ci int mode) 132162306a36Sopenharmony_ci{ 132262306a36Sopenharmony_ci struct dlm_lkb *lkb = NULL, *iter; 132362306a36Sopenharmony_ci 132462306a36Sopenharmony_ci list_for_each_entry(iter, head, lkb_statequeue) 132562306a36Sopenharmony_ci if (iter->lkb_rqmode < mode) { 132662306a36Sopenharmony_ci lkb = iter; 132762306a36Sopenharmony_ci list_add_tail(new, &iter->lkb_statequeue); 132862306a36Sopenharmony_ci break; 132962306a36Sopenharmony_ci } 133062306a36Sopenharmony_ci 133162306a36Sopenharmony_ci if (!lkb) 133262306a36Sopenharmony_ci list_add_tail(new, head); 133362306a36Sopenharmony_ci} 133462306a36Sopenharmony_ci 133562306a36Sopenharmony_ci/* add/remove lkb to rsb's grant/convert/wait queue */ 133662306a36Sopenharmony_ci 133762306a36Sopenharmony_cistatic void add_lkb(struct dlm_rsb *r, struct dlm_lkb *lkb, int status) 133862306a36Sopenharmony_ci{ 133962306a36Sopenharmony_ci kref_get(&lkb->lkb_ref); 134062306a36Sopenharmony_ci 134162306a36Sopenharmony_ci DLM_ASSERT(!lkb->lkb_status, dlm_print_lkb(lkb);); 134262306a36Sopenharmony_ci 134362306a36Sopenharmony_ci lkb->lkb_timestamp = ktime_get(); 134462306a36Sopenharmony_ci 134562306a36Sopenharmony_ci lkb->lkb_status = status; 134662306a36Sopenharmony_ci 134762306a36Sopenharmony_ci switch (status) { 134862306a36Sopenharmony_ci case DLM_LKSTS_WAITING: 134962306a36Sopenharmony_ci if (lkb->lkb_exflags & DLM_LKF_HEADQUE) 135062306a36Sopenharmony_ci list_add(&lkb->lkb_statequeue, &r->res_waitqueue); 135162306a36Sopenharmony_ci else 135262306a36Sopenharmony_ci list_add_tail(&lkb->lkb_statequeue, &r->res_waitqueue); 135362306a36Sopenharmony_ci break; 135462306a36Sopenharmony_ci case DLM_LKSTS_GRANTED: 135562306a36Sopenharmony_ci /* convention says granted locks kept in order of grmode */ 135662306a36Sopenharmony_ci lkb_add_ordered(&lkb->lkb_statequeue, &r->res_grantqueue, 135762306a36Sopenharmony_ci lkb->lkb_grmode); 135862306a36Sopenharmony_ci break; 135962306a36Sopenharmony_ci case DLM_LKSTS_CONVERT: 136062306a36Sopenharmony_ci if (lkb->lkb_exflags & DLM_LKF_HEADQUE) 136162306a36Sopenharmony_ci list_add(&lkb->lkb_statequeue, &r->res_convertqueue); 136262306a36Sopenharmony_ci else 136362306a36Sopenharmony_ci list_add_tail(&lkb->lkb_statequeue, 136462306a36Sopenharmony_ci &r->res_convertqueue); 136562306a36Sopenharmony_ci break; 136662306a36Sopenharmony_ci default: 136762306a36Sopenharmony_ci DLM_ASSERT(0, dlm_print_lkb(lkb); printk("sts=%d\n", status);); 136862306a36Sopenharmony_ci } 136962306a36Sopenharmony_ci} 137062306a36Sopenharmony_ci 137162306a36Sopenharmony_cistatic void del_lkb(struct dlm_rsb *r, struct dlm_lkb *lkb) 137262306a36Sopenharmony_ci{ 137362306a36Sopenharmony_ci lkb->lkb_status = 0; 137462306a36Sopenharmony_ci list_del(&lkb->lkb_statequeue); 137562306a36Sopenharmony_ci unhold_lkb(lkb); 137662306a36Sopenharmony_ci} 137762306a36Sopenharmony_ci 137862306a36Sopenharmony_cistatic void move_lkb(struct dlm_rsb *r, struct dlm_lkb *lkb, int sts) 137962306a36Sopenharmony_ci{ 138062306a36Sopenharmony_ci hold_lkb(lkb); 138162306a36Sopenharmony_ci del_lkb(r, lkb); 138262306a36Sopenharmony_ci add_lkb(r, lkb, sts); 138362306a36Sopenharmony_ci unhold_lkb(lkb); 138462306a36Sopenharmony_ci} 138562306a36Sopenharmony_ci 138662306a36Sopenharmony_cistatic int msg_reply_type(int mstype) 138762306a36Sopenharmony_ci{ 138862306a36Sopenharmony_ci switch (mstype) { 138962306a36Sopenharmony_ci case DLM_MSG_REQUEST: 139062306a36Sopenharmony_ci return DLM_MSG_REQUEST_REPLY; 139162306a36Sopenharmony_ci case DLM_MSG_CONVERT: 139262306a36Sopenharmony_ci return DLM_MSG_CONVERT_REPLY; 139362306a36Sopenharmony_ci case DLM_MSG_UNLOCK: 139462306a36Sopenharmony_ci return DLM_MSG_UNLOCK_REPLY; 139562306a36Sopenharmony_ci case DLM_MSG_CANCEL: 139662306a36Sopenharmony_ci return DLM_MSG_CANCEL_REPLY; 139762306a36Sopenharmony_ci case DLM_MSG_LOOKUP: 139862306a36Sopenharmony_ci return DLM_MSG_LOOKUP_REPLY; 139962306a36Sopenharmony_ci } 140062306a36Sopenharmony_ci return -1; 140162306a36Sopenharmony_ci} 140262306a36Sopenharmony_ci 140362306a36Sopenharmony_ci/* add/remove lkb from global waiters list of lkb's waiting for 140462306a36Sopenharmony_ci a reply from a remote node */ 140562306a36Sopenharmony_ci 140662306a36Sopenharmony_cistatic int add_to_waiters(struct dlm_lkb *lkb, int mstype, int to_nodeid) 140762306a36Sopenharmony_ci{ 140862306a36Sopenharmony_ci struct dlm_ls *ls = lkb->lkb_resource->res_ls; 140962306a36Sopenharmony_ci int error = 0; 141062306a36Sopenharmony_ci int wc; 141162306a36Sopenharmony_ci 141262306a36Sopenharmony_ci mutex_lock(&ls->ls_waiters_mutex); 141362306a36Sopenharmony_ci 141462306a36Sopenharmony_ci if (is_overlap_unlock(lkb) || 141562306a36Sopenharmony_ci (is_overlap_cancel(lkb) && (mstype == DLM_MSG_CANCEL))) { 141662306a36Sopenharmony_ci error = -EINVAL; 141762306a36Sopenharmony_ci goto out; 141862306a36Sopenharmony_ci } 141962306a36Sopenharmony_ci 142062306a36Sopenharmony_ci if (lkb->lkb_wait_type || is_overlap_cancel(lkb)) { 142162306a36Sopenharmony_ci switch (mstype) { 142262306a36Sopenharmony_ci case DLM_MSG_UNLOCK: 142362306a36Sopenharmony_ci set_bit(DLM_IFL_OVERLAP_UNLOCK_BIT, &lkb->lkb_iflags); 142462306a36Sopenharmony_ci break; 142562306a36Sopenharmony_ci case DLM_MSG_CANCEL: 142662306a36Sopenharmony_ci set_bit(DLM_IFL_OVERLAP_CANCEL_BIT, &lkb->lkb_iflags); 142762306a36Sopenharmony_ci break; 142862306a36Sopenharmony_ci default: 142962306a36Sopenharmony_ci error = -EBUSY; 143062306a36Sopenharmony_ci goto out; 143162306a36Sopenharmony_ci } 143262306a36Sopenharmony_ci wc = atomic_inc_return(&lkb->lkb_wait_count); 143362306a36Sopenharmony_ci hold_lkb(lkb); 143462306a36Sopenharmony_ci 143562306a36Sopenharmony_ci log_debug(ls, "addwait %x cur %d overlap %d count %d f %x", 143662306a36Sopenharmony_ci lkb->lkb_id, lkb->lkb_wait_type, mstype, wc, 143762306a36Sopenharmony_ci dlm_iflags_val(lkb)); 143862306a36Sopenharmony_ci goto out; 143962306a36Sopenharmony_ci } 144062306a36Sopenharmony_ci 144162306a36Sopenharmony_ci wc = atomic_fetch_inc(&lkb->lkb_wait_count); 144262306a36Sopenharmony_ci DLM_ASSERT(!wc, dlm_print_lkb(lkb); printk("wait_count %d\n", wc);); 144362306a36Sopenharmony_ci lkb->lkb_wait_type = mstype; 144462306a36Sopenharmony_ci lkb->lkb_wait_nodeid = to_nodeid; /* for debugging */ 144562306a36Sopenharmony_ci hold_lkb(lkb); 144662306a36Sopenharmony_ci list_add(&lkb->lkb_wait_reply, &ls->ls_waiters); 144762306a36Sopenharmony_ci out: 144862306a36Sopenharmony_ci if (error) 144962306a36Sopenharmony_ci log_error(ls, "addwait error %x %d flags %x %d %d %s", 145062306a36Sopenharmony_ci lkb->lkb_id, error, dlm_iflags_val(lkb), mstype, 145162306a36Sopenharmony_ci lkb->lkb_wait_type, lkb->lkb_resource->res_name); 145262306a36Sopenharmony_ci mutex_unlock(&ls->ls_waiters_mutex); 145362306a36Sopenharmony_ci return error; 145462306a36Sopenharmony_ci} 145562306a36Sopenharmony_ci 145662306a36Sopenharmony_ci/* We clear the RESEND flag because we might be taking an lkb off the waiters 145762306a36Sopenharmony_ci list as part of process_requestqueue (e.g. a lookup that has an optimized 145862306a36Sopenharmony_ci request reply on the requestqueue) between dlm_recover_waiters_pre() which 145962306a36Sopenharmony_ci set RESEND and dlm_recover_waiters_post() */ 146062306a36Sopenharmony_ci 146162306a36Sopenharmony_cistatic int _remove_from_waiters(struct dlm_lkb *lkb, int mstype, 146262306a36Sopenharmony_ci const struct dlm_message *ms) 146362306a36Sopenharmony_ci{ 146462306a36Sopenharmony_ci struct dlm_ls *ls = lkb->lkb_resource->res_ls; 146562306a36Sopenharmony_ci int overlap_done = 0; 146662306a36Sopenharmony_ci 146762306a36Sopenharmony_ci if (mstype == DLM_MSG_UNLOCK_REPLY && 146862306a36Sopenharmony_ci test_and_clear_bit(DLM_IFL_OVERLAP_UNLOCK_BIT, &lkb->lkb_iflags)) { 146962306a36Sopenharmony_ci log_debug(ls, "remwait %x unlock_reply overlap", lkb->lkb_id); 147062306a36Sopenharmony_ci overlap_done = 1; 147162306a36Sopenharmony_ci goto out_del; 147262306a36Sopenharmony_ci } 147362306a36Sopenharmony_ci 147462306a36Sopenharmony_ci if (mstype == DLM_MSG_CANCEL_REPLY && 147562306a36Sopenharmony_ci test_and_clear_bit(DLM_IFL_OVERLAP_CANCEL_BIT, &lkb->lkb_iflags)) { 147662306a36Sopenharmony_ci log_debug(ls, "remwait %x cancel_reply overlap", lkb->lkb_id); 147762306a36Sopenharmony_ci overlap_done = 1; 147862306a36Sopenharmony_ci goto out_del; 147962306a36Sopenharmony_ci } 148062306a36Sopenharmony_ci 148162306a36Sopenharmony_ci /* Cancel state was preemptively cleared by a successful convert, 148262306a36Sopenharmony_ci see next comment, nothing to do. */ 148362306a36Sopenharmony_ci 148462306a36Sopenharmony_ci if ((mstype == DLM_MSG_CANCEL_REPLY) && 148562306a36Sopenharmony_ci (lkb->lkb_wait_type != DLM_MSG_CANCEL)) { 148662306a36Sopenharmony_ci log_debug(ls, "remwait %x cancel_reply wait_type %d", 148762306a36Sopenharmony_ci lkb->lkb_id, lkb->lkb_wait_type); 148862306a36Sopenharmony_ci return -1; 148962306a36Sopenharmony_ci } 149062306a36Sopenharmony_ci 149162306a36Sopenharmony_ci /* Remove for the convert reply, and premptively remove for the 149262306a36Sopenharmony_ci cancel reply. A convert has been granted while there's still 149362306a36Sopenharmony_ci an outstanding cancel on it (the cancel is moot and the result 149462306a36Sopenharmony_ci in the cancel reply should be 0). We preempt the cancel reply 149562306a36Sopenharmony_ci because the app gets the convert result and then can follow up 149662306a36Sopenharmony_ci with another op, like convert. This subsequent op would see the 149762306a36Sopenharmony_ci lingering state of the cancel and fail with -EBUSY. */ 149862306a36Sopenharmony_ci 149962306a36Sopenharmony_ci if ((mstype == DLM_MSG_CONVERT_REPLY) && 150062306a36Sopenharmony_ci (lkb->lkb_wait_type == DLM_MSG_CONVERT) && ms && !ms->m_result && 150162306a36Sopenharmony_ci test_and_clear_bit(DLM_IFL_OVERLAP_CANCEL_BIT, &lkb->lkb_iflags)) { 150262306a36Sopenharmony_ci log_debug(ls, "remwait %x convert_reply zap overlap_cancel", 150362306a36Sopenharmony_ci lkb->lkb_id); 150462306a36Sopenharmony_ci lkb->lkb_wait_type = 0; 150562306a36Sopenharmony_ci atomic_dec(&lkb->lkb_wait_count); 150662306a36Sopenharmony_ci unhold_lkb(lkb); 150762306a36Sopenharmony_ci goto out_del; 150862306a36Sopenharmony_ci } 150962306a36Sopenharmony_ci 151062306a36Sopenharmony_ci /* N.B. type of reply may not always correspond to type of original 151162306a36Sopenharmony_ci msg due to lookup->request optimization, verify others? */ 151262306a36Sopenharmony_ci 151362306a36Sopenharmony_ci if (lkb->lkb_wait_type) { 151462306a36Sopenharmony_ci lkb->lkb_wait_type = 0; 151562306a36Sopenharmony_ci goto out_del; 151662306a36Sopenharmony_ci } 151762306a36Sopenharmony_ci 151862306a36Sopenharmony_ci log_error(ls, "remwait error %x remote %d %x msg %d flags %x no wait", 151962306a36Sopenharmony_ci lkb->lkb_id, ms ? le32_to_cpu(ms->m_header.h_nodeid) : 0, 152062306a36Sopenharmony_ci lkb->lkb_remid, mstype, dlm_iflags_val(lkb)); 152162306a36Sopenharmony_ci return -1; 152262306a36Sopenharmony_ci 152362306a36Sopenharmony_ci out_del: 152462306a36Sopenharmony_ci /* the force-unlock/cancel has completed and we haven't recvd a reply 152562306a36Sopenharmony_ci to the op that was in progress prior to the unlock/cancel; we 152662306a36Sopenharmony_ci give up on any reply to the earlier op. FIXME: not sure when/how 152762306a36Sopenharmony_ci this would happen */ 152862306a36Sopenharmony_ci 152962306a36Sopenharmony_ci if (overlap_done && lkb->lkb_wait_type) { 153062306a36Sopenharmony_ci log_error(ls, "remwait error %x reply %d wait_type %d overlap", 153162306a36Sopenharmony_ci lkb->lkb_id, mstype, lkb->lkb_wait_type); 153262306a36Sopenharmony_ci atomic_dec(&lkb->lkb_wait_count); 153362306a36Sopenharmony_ci unhold_lkb(lkb); 153462306a36Sopenharmony_ci lkb->lkb_wait_type = 0; 153562306a36Sopenharmony_ci } 153662306a36Sopenharmony_ci 153762306a36Sopenharmony_ci DLM_ASSERT(atomic_read(&lkb->lkb_wait_count), dlm_print_lkb(lkb);); 153862306a36Sopenharmony_ci 153962306a36Sopenharmony_ci clear_bit(DLM_IFL_RESEND_BIT, &lkb->lkb_iflags); 154062306a36Sopenharmony_ci if (atomic_dec_and_test(&lkb->lkb_wait_count)) 154162306a36Sopenharmony_ci list_del_init(&lkb->lkb_wait_reply); 154262306a36Sopenharmony_ci unhold_lkb(lkb); 154362306a36Sopenharmony_ci return 0; 154462306a36Sopenharmony_ci} 154562306a36Sopenharmony_ci 154662306a36Sopenharmony_cistatic int remove_from_waiters(struct dlm_lkb *lkb, int mstype) 154762306a36Sopenharmony_ci{ 154862306a36Sopenharmony_ci struct dlm_ls *ls = lkb->lkb_resource->res_ls; 154962306a36Sopenharmony_ci int error; 155062306a36Sopenharmony_ci 155162306a36Sopenharmony_ci mutex_lock(&ls->ls_waiters_mutex); 155262306a36Sopenharmony_ci error = _remove_from_waiters(lkb, mstype, NULL); 155362306a36Sopenharmony_ci mutex_unlock(&ls->ls_waiters_mutex); 155462306a36Sopenharmony_ci return error; 155562306a36Sopenharmony_ci} 155662306a36Sopenharmony_ci 155762306a36Sopenharmony_ci/* Handles situations where we might be processing a "fake" or "local" reply in 155862306a36Sopenharmony_ci which we can't try to take waiters_mutex again. */ 155962306a36Sopenharmony_ci 156062306a36Sopenharmony_cistatic int remove_from_waiters_ms(struct dlm_lkb *lkb, 156162306a36Sopenharmony_ci const struct dlm_message *ms, bool local) 156262306a36Sopenharmony_ci{ 156362306a36Sopenharmony_ci struct dlm_ls *ls = lkb->lkb_resource->res_ls; 156462306a36Sopenharmony_ci int error; 156562306a36Sopenharmony_ci 156662306a36Sopenharmony_ci if (!local) 156762306a36Sopenharmony_ci mutex_lock(&ls->ls_waiters_mutex); 156862306a36Sopenharmony_ci error = _remove_from_waiters(lkb, le32_to_cpu(ms->m_type), ms); 156962306a36Sopenharmony_ci if (!local) 157062306a36Sopenharmony_ci mutex_unlock(&ls->ls_waiters_mutex); 157162306a36Sopenharmony_ci return error; 157262306a36Sopenharmony_ci} 157362306a36Sopenharmony_ci 157462306a36Sopenharmony_cistatic void shrink_bucket(struct dlm_ls *ls, int b) 157562306a36Sopenharmony_ci{ 157662306a36Sopenharmony_ci struct rb_node *n, *next; 157762306a36Sopenharmony_ci struct dlm_rsb *r; 157862306a36Sopenharmony_ci char *name; 157962306a36Sopenharmony_ci int our_nodeid = dlm_our_nodeid(); 158062306a36Sopenharmony_ci int remote_count = 0; 158162306a36Sopenharmony_ci int need_shrink = 0; 158262306a36Sopenharmony_ci int i, len, rv; 158362306a36Sopenharmony_ci 158462306a36Sopenharmony_ci memset(&ls->ls_remove_lens, 0, sizeof(int) * DLM_REMOVE_NAMES_MAX); 158562306a36Sopenharmony_ci 158662306a36Sopenharmony_ci spin_lock(&ls->ls_rsbtbl[b].lock); 158762306a36Sopenharmony_ci 158862306a36Sopenharmony_ci if (!test_bit(DLM_RTF_SHRINK_BIT, &ls->ls_rsbtbl[b].flags)) { 158962306a36Sopenharmony_ci spin_unlock(&ls->ls_rsbtbl[b].lock); 159062306a36Sopenharmony_ci return; 159162306a36Sopenharmony_ci } 159262306a36Sopenharmony_ci 159362306a36Sopenharmony_ci for (n = rb_first(&ls->ls_rsbtbl[b].toss); n; n = next) { 159462306a36Sopenharmony_ci next = rb_next(n); 159562306a36Sopenharmony_ci r = rb_entry(n, struct dlm_rsb, res_hashnode); 159662306a36Sopenharmony_ci 159762306a36Sopenharmony_ci /* If we're the directory record for this rsb, and 159862306a36Sopenharmony_ci we're not the master of it, then we need to wait 159962306a36Sopenharmony_ci for the master node to send us a dir remove for 160062306a36Sopenharmony_ci before removing the dir record. */ 160162306a36Sopenharmony_ci 160262306a36Sopenharmony_ci if (!dlm_no_directory(ls) && 160362306a36Sopenharmony_ci (r->res_master_nodeid != our_nodeid) && 160462306a36Sopenharmony_ci (dlm_dir_nodeid(r) == our_nodeid)) { 160562306a36Sopenharmony_ci continue; 160662306a36Sopenharmony_ci } 160762306a36Sopenharmony_ci 160862306a36Sopenharmony_ci need_shrink = 1; 160962306a36Sopenharmony_ci 161062306a36Sopenharmony_ci if (!time_after_eq(jiffies, r->res_toss_time + 161162306a36Sopenharmony_ci dlm_config.ci_toss_secs * HZ)) { 161262306a36Sopenharmony_ci continue; 161362306a36Sopenharmony_ci } 161462306a36Sopenharmony_ci 161562306a36Sopenharmony_ci if (!dlm_no_directory(ls) && 161662306a36Sopenharmony_ci (r->res_master_nodeid == our_nodeid) && 161762306a36Sopenharmony_ci (dlm_dir_nodeid(r) != our_nodeid)) { 161862306a36Sopenharmony_ci 161962306a36Sopenharmony_ci /* We're the master of this rsb but we're not 162062306a36Sopenharmony_ci the directory record, so we need to tell the 162162306a36Sopenharmony_ci dir node to remove the dir record. */ 162262306a36Sopenharmony_ci 162362306a36Sopenharmony_ci ls->ls_remove_lens[remote_count] = r->res_length; 162462306a36Sopenharmony_ci memcpy(ls->ls_remove_names[remote_count], r->res_name, 162562306a36Sopenharmony_ci DLM_RESNAME_MAXLEN); 162662306a36Sopenharmony_ci remote_count++; 162762306a36Sopenharmony_ci 162862306a36Sopenharmony_ci if (remote_count >= DLM_REMOVE_NAMES_MAX) 162962306a36Sopenharmony_ci break; 163062306a36Sopenharmony_ci continue; 163162306a36Sopenharmony_ci } 163262306a36Sopenharmony_ci 163362306a36Sopenharmony_ci if (!kref_put(&r->res_ref, kill_rsb)) { 163462306a36Sopenharmony_ci log_error(ls, "tossed rsb in use %s", r->res_name); 163562306a36Sopenharmony_ci continue; 163662306a36Sopenharmony_ci } 163762306a36Sopenharmony_ci 163862306a36Sopenharmony_ci rb_erase(&r->res_hashnode, &ls->ls_rsbtbl[b].toss); 163962306a36Sopenharmony_ci dlm_free_rsb(r); 164062306a36Sopenharmony_ci } 164162306a36Sopenharmony_ci 164262306a36Sopenharmony_ci if (need_shrink) 164362306a36Sopenharmony_ci set_bit(DLM_RTF_SHRINK_BIT, &ls->ls_rsbtbl[b].flags); 164462306a36Sopenharmony_ci else 164562306a36Sopenharmony_ci clear_bit(DLM_RTF_SHRINK_BIT, &ls->ls_rsbtbl[b].flags); 164662306a36Sopenharmony_ci spin_unlock(&ls->ls_rsbtbl[b].lock); 164762306a36Sopenharmony_ci 164862306a36Sopenharmony_ci /* 164962306a36Sopenharmony_ci * While searching for rsb's to free, we found some that require 165062306a36Sopenharmony_ci * remote removal. We leave them in place and find them again here 165162306a36Sopenharmony_ci * so there is a very small gap between removing them from the toss 165262306a36Sopenharmony_ci * list and sending the removal. Keeping this gap small is 165362306a36Sopenharmony_ci * important to keep us (the master node) from being out of sync 165462306a36Sopenharmony_ci * with the remote dir node for very long. 165562306a36Sopenharmony_ci */ 165662306a36Sopenharmony_ci 165762306a36Sopenharmony_ci for (i = 0; i < remote_count; i++) { 165862306a36Sopenharmony_ci name = ls->ls_remove_names[i]; 165962306a36Sopenharmony_ci len = ls->ls_remove_lens[i]; 166062306a36Sopenharmony_ci 166162306a36Sopenharmony_ci spin_lock(&ls->ls_rsbtbl[b].lock); 166262306a36Sopenharmony_ci rv = dlm_search_rsb_tree(&ls->ls_rsbtbl[b].toss, name, len, &r); 166362306a36Sopenharmony_ci if (rv) { 166462306a36Sopenharmony_ci spin_unlock(&ls->ls_rsbtbl[b].lock); 166562306a36Sopenharmony_ci log_debug(ls, "remove_name not toss %s", name); 166662306a36Sopenharmony_ci continue; 166762306a36Sopenharmony_ci } 166862306a36Sopenharmony_ci 166962306a36Sopenharmony_ci if (r->res_master_nodeid != our_nodeid) { 167062306a36Sopenharmony_ci spin_unlock(&ls->ls_rsbtbl[b].lock); 167162306a36Sopenharmony_ci log_debug(ls, "remove_name master %d dir %d our %d %s", 167262306a36Sopenharmony_ci r->res_master_nodeid, r->res_dir_nodeid, 167362306a36Sopenharmony_ci our_nodeid, name); 167462306a36Sopenharmony_ci continue; 167562306a36Sopenharmony_ci } 167662306a36Sopenharmony_ci 167762306a36Sopenharmony_ci if (r->res_dir_nodeid == our_nodeid) { 167862306a36Sopenharmony_ci /* should never happen */ 167962306a36Sopenharmony_ci spin_unlock(&ls->ls_rsbtbl[b].lock); 168062306a36Sopenharmony_ci log_error(ls, "remove_name dir %d master %d our %d %s", 168162306a36Sopenharmony_ci r->res_dir_nodeid, r->res_master_nodeid, 168262306a36Sopenharmony_ci our_nodeid, name); 168362306a36Sopenharmony_ci continue; 168462306a36Sopenharmony_ci } 168562306a36Sopenharmony_ci 168662306a36Sopenharmony_ci if (!time_after_eq(jiffies, r->res_toss_time + 168762306a36Sopenharmony_ci dlm_config.ci_toss_secs * HZ)) { 168862306a36Sopenharmony_ci spin_unlock(&ls->ls_rsbtbl[b].lock); 168962306a36Sopenharmony_ci log_debug(ls, "remove_name toss_time %lu now %lu %s", 169062306a36Sopenharmony_ci r->res_toss_time, jiffies, name); 169162306a36Sopenharmony_ci continue; 169262306a36Sopenharmony_ci } 169362306a36Sopenharmony_ci 169462306a36Sopenharmony_ci if (!kref_put(&r->res_ref, kill_rsb)) { 169562306a36Sopenharmony_ci spin_unlock(&ls->ls_rsbtbl[b].lock); 169662306a36Sopenharmony_ci log_error(ls, "remove_name in use %s", name); 169762306a36Sopenharmony_ci continue; 169862306a36Sopenharmony_ci } 169962306a36Sopenharmony_ci 170062306a36Sopenharmony_ci rb_erase(&r->res_hashnode, &ls->ls_rsbtbl[b].toss); 170162306a36Sopenharmony_ci send_remove(r); 170262306a36Sopenharmony_ci spin_unlock(&ls->ls_rsbtbl[b].lock); 170362306a36Sopenharmony_ci 170462306a36Sopenharmony_ci dlm_free_rsb(r); 170562306a36Sopenharmony_ci } 170662306a36Sopenharmony_ci} 170762306a36Sopenharmony_ci 170862306a36Sopenharmony_civoid dlm_scan_rsbs(struct dlm_ls *ls) 170962306a36Sopenharmony_ci{ 171062306a36Sopenharmony_ci int i; 171162306a36Sopenharmony_ci 171262306a36Sopenharmony_ci for (i = 0; i < ls->ls_rsbtbl_size; i++) { 171362306a36Sopenharmony_ci shrink_bucket(ls, i); 171462306a36Sopenharmony_ci if (dlm_locking_stopped(ls)) 171562306a36Sopenharmony_ci break; 171662306a36Sopenharmony_ci cond_resched(); 171762306a36Sopenharmony_ci } 171862306a36Sopenharmony_ci} 171962306a36Sopenharmony_ci 172062306a36Sopenharmony_ci/* lkb is master or local copy */ 172162306a36Sopenharmony_ci 172262306a36Sopenharmony_cistatic void set_lvb_lock(struct dlm_rsb *r, struct dlm_lkb *lkb) 172362306a36Sopenharmony_ci{ 172462306a36Sopenharmony_ci int b, len = r->res_ls->ls_lvblen; 172562306a36Sopenharmony_ci 172662306a36Sopenharmony_ci /* b=1 lvb returned to caller 172762306a36Sopenharmony_ci b=0 lvb written to rsb or invalidated 172862306a36Sopenharmony_ci b=-1 do nothing */ 172962306a36Sopenharmony_ci 173062306a36Sopenharmony_ci b = dlm_lvb_operations[lkb->lkb_grmode + 1][lkb->lkb_rqmode + 1]; 173162306a36Sopenharmony_ci 173262306a36Sopenharmony_ci if (b == 1) { 173362306a36Sopenharmony_ci if (!lkb->lkb_lvbptr) 173462306a36Sopenharmony_ci return; 173562306a36Sopenharmony_ci 173662306a36Sopenharmony_ci if (!(lkb->lkb_exflags & DLM_LKF_VALBLK)) 173762306a36Sopenharmony_ci return; 173862306a36Sopenharmony_ci 173962306a36Sopenharmony_ci if (!r->res_lvbptr) 174062306a36Sopenharmony_ci return; 174162306a36Sopenharmony_ci 174262306a36Sopenharmony_ci memcpy(lkb->lkb_lvbptr, r->res_lvbptr, len); 174362306a36Sopenharmony_ci lkb->lkb_lvbseq = r->res_lvbseq; 174462306a36Sopenharmony_ci 174562306a36Sopenharmony_ci } else if (b == 0) { 174662306a36Sopenharmony_ci if (lkb->lkb_exflags & DLM_LKF_IVVALBLK) { 174762306a36Sopenharmony_ci rsb_set_flag(r, RSB_VALNOTVALID); 174862306a36Sopenharmony_ci return; 174962306a36Sopenharmony_ci } 175062306a36Sopenharmony_ci 175162306a36Sopenharmony_ci if (!lkb->lkb_lvbptr) 175262306a36Sopenharmony_ci return; 175362306a36Sopenharmony_ci 175462306a36Sopenharmony_ci if (!(lkb->lkb_exflags & DLM_LKF_VALBLK)) 175562306a36Sopenharmony_ci return; 175662306a36Sopenharmony_ci 175762306a36Sopenharmony_ci if (!r->res_lvbptr) 175862306a36Sopenharmony_ci r->res_lvbptr = dlm_allocate_lvb(r->res_ls); 175962306a36Sopenharmony_ci 176062306a36Sopenharmony_ci if (!r->res_lvbptr) 176162306a36Sopenharmony_ci return; 176262306a36Sopenharmony_ci 176362306a36Sopenharmony_ci memcpy(r->res_lvbptr, lkb->lkb_lvbptr, len); 176462306a36Sopenharmony_ci r->res_lvbseq++; 176562306a36Sopenharmony_ci lkb->lkb_lvbseq = r->res_lvbseq; 176662306a36Sopenharmony_ci rsb_clear_flag(r, RSB_VALNOTVALID); 176762306a36Sopenharmony_ci } 176862306a36Sopenharmony_ci 176962306a36Sopenharmony_ci if (rsb_flag(r, RSB_VALNOTVALID)) 177062306a36Sopenharmony_ci set_bit(DLM_SBF_VALNOTVALID_BIT, &lkb->lkb_sbflags); 177162306a36Sopenharmony_ci} 177262306a36Sopenharmony_ci 177362306a36Sopenharmony_cistatic void set_lvb_unlock(struct dlm_rsb *r, struct dlm_lkb *lkb) 177462306a36Sopenharmony_ci{ 177562306a36Sopenharmony_ci if (lkb->lkb_grmode < DLM_LOCK_PW) 177662306a36Sopenharmony_ci return; 177762306a36Sopenharmony_ci 177862306a36Sopenharmony_ci if (lkb->lkb_exflags & DLM_LKF_IVVALBLK) { 177962306a36Sopenharmony_ci rsb_set_flag(r, RSB_VALNOTVALID); 178062306a36Sopenharmony_ci return; 178162306a36Sopenharmony_ci } 178262306a36Sopenharmony_ci 178362306a36Sopenharmony_ci if (!lkb->lkb_lvbptr) 178462306a36Sopenharmony_ci return; 178562306a36Sopenharmony_ci 178662306a36Sopenharmony_ci if (!(lkb->lkb_exflags & DLM_LKF_VALBLK)) 178762306a36Sopenharmony_ci return; 178862306a36Sopenharmony_ci 178962306a36Sopenharmony_ci if (!r->res_lvbptr) 179062306a36Sopenharmony_ci r->res_lvbptr = dlm_allocate_lvb(r->res_ls); 179162306a36Sopenharmony_ci 179262306a36Sopenharmony_ci if (!r->res_lvbptr) 179362306a36Sopenharmony_ci return; 179462306a36Sopenharmony_ci 179562306a36Sopenharmony_ci memcpy(r->res_lvbptr, lkb->lkb_lvbptr, r->res_ls->ls_lvblen); 179662306a36Sopenharmony_ci r->res_lvbseq++; 179762306a36Sopenharmony_ci rsb_clear_flag(r, RSB_VALNOTVALID); 179862306a36Sopenharmony_ci} 179962306a36Sopenharmony_ci 180062306a36Sopenharmony_ci/* lkb is process copy (pc) */ 180162306a36Sopenharmony_ci 180262306a36Sopenharmony_cistatic void set_lvb_lock_pc(struct dlm_rsb *r, struct dlm_lkb *lkb, 180362306a36Sopenharmony_ci const struct dlm_message *ms) 180462306a36Sopenharmony_ci{ 180562306a36Sopenharmony_ci int b; 180662306a36Sopenharmony_ci 180762306a36Sopenharmony_ci if (!lkb->lkb_lvbptr) 180862306a36Sopenharmony_ci return; 180962306a36Sopenharmony_ci 181062306a36Sopenharmony_ci if (!(lkb->lkb_exflags & DLM_LKF_VALBLK)) 181162306a36Sopenharmony_ci return; 181262306a36Sopenharmony_ci 181362306a36Sopenharmony_ci b = dlm_lvb_operations[lkb->lkb_grmode + 1][lkb->lkb_rqmode + 1]; 181462306a36Sopenharmony_ci if (b == 1) { 181562306a36Sopenharmony_ci int len = receive_extralen(ms); 181662306a36Sopenharmony_ci if (len > r->res_ls->ls_lvblen) 181762306a36Sopenharmony_ci len = r->res_ls->ls_lvblen; 181862306a36Sopenharmony_ci memcpy(lkb->lkb_lvbptr, ms->m_extra, len); 181962306a36Sopenharmony_ci lkb->lkb_lvbseq = le32_to_cpu(ms->m_lvbseq); 182062306a36Sopenharmony_ci } 182162306a36Sopenharmony_ci} 182262306a36Sopenharmony_ci 182362306a36Sopenharmony_ci/* Manipulate lkb's on rsb's convert/granted/waiting queues 182462306a36Sopenharmony_ci remove_lock -- used for unlock, removes lkb from granted 182562306a36Sopenharmony_ci revert_lock -- used for cancel, moves lkb from convert to granted 182662306a36Sopenharmony_ci grant_lock -- used for request and convert, adds lkb to granted or 182762306a36Sopenharmony_ci moves lkb from convert or waiting to granted 182862306a36Sopenharmony_ci 182962306a36Sopenharmony_ci Each of these is used for master or local copy lkb's. There is 183062306a36Sopenharmony_ci also a _pc() variation used to make the corresponding change on 183162306a36Sopenharmony_ci a process copy (pc) lkb. */ 183262306a36Sopenharmony_ci 183362306a36Sopenharmony_cistatic void _remove_lock(struct dlm_rsb *r, struct dlm_lkb *lkb) 183462306a36Sopenharmony_ci{ 183562306a36Sopenharmony_ci del_lkb(r, lkb); 183662306a36Sopenharmony_ci lkb->lkb_grmode = DLM_LOCK_IV; 183762306a36Sopenharmony_ci /* this unhold undoes the original ref from create_lkb() 183862306a36Sopenharmony_ci so this leads to the lkb being freed */ 183962306a36Sopenharmony_ci unhold_lkb(lkb); 184062306a36Sopenharmony_ci} 184162306a36Sopenharmony_ci 184262306a36Sopenharmony_cistatic void remove_lock(struct dlm_rsb *r, struct dlm_lkb *lkb) 184362306a36Sopenharmony_ci{ 184462306a36Sopenharmony_ci set_lvb_unlock(r, lkb); 184562306a36Sopenharmony_ci _remove_lock(r, lkb); 184662306a36Sopenharmony_ci} 184762306a36Sopenharmony_ci 184862306a36Sopenharmony_cistatic void remove_lock_pc(struct dlm_rsb *r, struct dlm_lkb *lkb) 184962306a36Sopenharmony_ci{ 185062306a36Sopenharmony_ci _remove_lock(r, lkb); 185162306a36Sopenharmony_ci} 185262306a36Sopenharmony_ci 185362306a36Sopenharmony_ci/* returns: 0 did nothing 185462306a36Sopenharmony_ci 1 moved lock to granted 185562306a36Sopenharmony_ci -1 removed lock */ 185662306a36Sopenharmony_ci 185762306a36Sopenharmony_cistatic int revert_lock(struct dlm_rsb *r, struct dlm_lkb *lkb) 185862306a36Sopenharmony_ci{ 185962306a36Sopenharmony_ci int rv = 0; 186062306a36Sopenharmony_ci 186162306a36Sopenharmony_ci lkb->lkb_rqmode = DLM_LOCK_IV; 186262306a36Sopenharmony_ci 186362306a36Sopenharmony_ci switch (lkb->lkb_status) { 186462306a36Sopenharmony_ci case DLM_LKSTS_GRANTED: 186562306a36Sopenharmony_ci break; 186662306a36Sopenharmony_ci case DLM_LKSTS_CONVERT: 186762306a36Sopenharmony_ci move_lkb(r, lkb, DLM_LKSTS_GRANTED); 186862306a36Sopenharmony_ci rv = 1; 186962306a36Sopenharmony_ci break; 187062306a36Sopenharmony_ci case DLM_LKSTS_WAITING: 187162306a36Sopenharmony_ci del_lkb(r, lkb); 187262306a36Sopenharmony_ci lkb->lkb_grmode = DLM_LOCK_IV; 187362306a36Sopenharmony_ci /* this unhold undoes the original ref from create_lkb() 187462306a36Sopenharmony_ci so this leads to the lkb being freed */ 187562306a36Sopenharmony_ci unhold_lkb(lkb); 187662306a36Sopenharmony_ci rv = -1; 187762306a36Sopenharmony_ci break; 187862306a36Sopenharmony_ci default: 187962306a36Sopenharmony_ci log_print("invalid status for revert %d", lkb->lkb_status); 188062306a36Sopenharmony_ci } 188162306a36Sopenharmony_ci return rv; 188262306a36Sopenharmony_ci} 188362306a36Sopenharmony_ci 188462306a36Sopenharmony_cistatic int revert_lock_pc(struct dlm_rsb *r, struct dlm_lkb *lkb) 188562306a36Sopenharmony_ci{ 188662306a36Sopenharmony_ci return revert_lock(r, lkb); 188762306a36Sopenharmony_ci} 188862306a36Sopenharmony_ci 188962306a36Sopenharmony_cistatic void _grant_lock(struct dlm_rsb *r, struct dlm_lkb *lkb) 189062306a36Sopenharmony_ci{ 189162306a36Sopenharmony_ci if (lkb->lkb_grmode != lkb->lkb_rqmode) { 189262306a36Sopenharmony_ci lkb->lkb_grmode = lkb->lkb_rqmode; 189362306a36Sopenharmony_ci if (lkb->lkb_status) 189462306a36Sopenharmony_ci move_lkb(r, lkb, DLM_LKSTS_GRANTED); 189562306a36Sopenharmony_ci else 189662306a36Sopenharmony_ci add_lkb(r, lkb, DLM_LKSTS_GRANTED); 189762306a36Sopenharmony_ci } 189862306a36Sopenharmony_ci 189962306a36Sopenharmony_ci lkb->lkb_rqmode = DLM_LOCK_IV; 190062306a36Sopenharmony_ci lkb->lkb_highbast = 0; 190162306a36Sopenharmony_ci} 190262306a36Sopenharmony_ci 190362306a36Sopenharmony_cistatic void grant_lock(struct dlm_rsb *r, struct dlm_lkb *lkb) 190462306a36Sopenharmony_ci{ 190562306a36Sopenharmony_ci set_lvb_lock(r, lkb); 190662306a36Sopenharmony_ci _grant_lock(r, lkb); 190762306a36Sopenharmony_ci} 190862306a36Sopenharmony_ci 190962306a36Sopenharmony_cistatic void grant_lock_pc(struct dlm_rsb *r, struct dlm_lkb *lkb, 191062306a36Sopenharmony_ci const struct dlm_message *ms) 191162306a36Sopenharmony_ci{ 191262306a36Sopenharmony_ci set_lvb_lock_pc(r, lkb, ms); 191362306a36Sopenharmony_ci _grant_lock(r, lkb); 191462306a36Sopenharmony_ci} 191562306a36Sopenharmony_ci 191662306a36Sopenharmony_ci/* called by grant_pending_locks() which means an async grant message must 191762306a36Sopenharmony_ci be sent to the requesting node in addition to granting the lock if the 191862306a36Sopenharmony_ci lkb belongs to a remote node. */ 191962306a36Sopenharmony_ci 192062306a36Sopenharmony_cistatic void grant_lock_pending(struct dlm_rsb *r, struct dlm_lkb *lkb) 192162306a36Sopenharmony_ci{ 192262306a36Sopenharmony_ci grant_lock(r, lkb); 192362306a36Sopenharmony_ci if (is_master_copy(lkb)) 192462306a36Sopenharmony_ci send_grant(r, lkb); 192562306a36Sopenharmony_ci else 192662306a36Sopenharmony_ci queue_cast(r, lkb, 0); 192762306a36Sopenharmony_ci} 192862306a36Sopenharmony_ci 192962306a36Sopenharmony_ci/* The special CONVDEADLK, ALTPR and ALTCW flags allow the master to 193062306a36Sopenharmony_ci change the granted/requested modes. We're munging things accordingly in 193162306a36Sopenharmony_ci the process copy. 193262306a36Sopenharmony_ci CONVDEADLK: our grmode may have been forced down to NL to resolve a 193362306a36Sopenharmony_ci conversion deadlock 193462306a36Sopenharmony_ci ALTPR/ALTCW: our rqmode may have been changed to PR or CW to become 193562306a36Sopenharmony_ci compatible with other granted locks */ 193662306a36Sopenharmony_ci 193762306a36Sopenharmony_cistatic void munge_demoted(struct dlm_lkb *lkb) 193862306a36Sopenharmony_ci{ 193962306a36Sopenharmony_ci if (lkb->lkb_rqmode == DLM_LOCK_IV || lkb->lkb_grmode == DLM_LOCK_IV) { 194062306a36Sopenharmony_ci log_print("munge_demoted %x invalid modes gr %d rq %d", 194162306a36Sopenharmony_ci lkb->lkb_id, lkb->lkb_grmode, lkb->lkb_rqmode); 194262306a36Sopenharmony_ci return; 194362306a36Sopenharmony_ci } 194462306a36Sopenharmony_ci 194562306a36Sopenharmony_ci lkb->lkb_grmode = DLM_LOCK_NL; 194662306a36Sopenharmony_ci} 194762306a36Sopenharmony_ci 194862306a36Sopenharmony_cistatic void munge_altmode(struct dlm_lkb *lkb, const struct dlm_message *ms) 194962306a36Sopenharmony_ci{ 195062306a36Sopenharmony_ci if (ms->m_type != cpu_to_le32(DLM_MSG_REQUEST_REPLY) && 195162306a36Sopenharmony_ci ms->m_type != cpu_to_le32(DLM_MSG_GRANT)) { 195262306a36Sopenharmony_ci log_print("munge_altmode %x invalid reply type %d", 195362306a36Sopenharmony_ci lkb->lkb_id, le32_to_cpu(ms->m_type)); 195462306a36Sopenharmony_ci return; 195562306a36Sopenharmony_ci } 195662306a36Sopenharmony_ci 195762306a36Sopenharmony_ci if (lkb->lkb_exflags & DLM_LKF_ALTPR) 195862306a36Sopenharmony_ci lkb->lkb_rqmode = DLM_LOCK_PR; 195962306a36Sopenharmony_ci else if (lkb->lkb_exflags & DLM_LKF_ALTCW) 196062306a36Sopenharmony_ci lkb->lkb_rqmode = DLM_LOCK_CW; 196162306a36Sopenharmony_ci else { 196262306a36Sopenharmony_ci log_print("munge_altmode invalid exflags %x", lkb->lkb_exflags); 196362306a36Sopenharmony_ci dlm_print_lkb(lkb); 196462306a36Sopenharmony_ci } 196562306a36Sopenharmony_ci} 196662306a36Sopenharmony_ci 196762306a36Sopenharmony_cistatic inline int first_in_list(struct dlm_lkb *lkb, struct list_head *head) 196862306a36Sopenharmony_ci{ 196962306a36Sopenharmony_ci struct dlm_lkb *first = list_entry(head->next, struct dlm_lkb, 197062306a36Sopenharmony_ci lkb_statequeue); 197162306a36Sopenharmony_ci if (lkb->lkb_id == first->lkb_id) 197262306a36Sopenharmony_ci return 1; 197362306a36Sopenharmony_ci 197462306a36Sopenharmony_ci return 0; 197562306a36Sopenharmony_ci} 197662306a36Sopenharmony_ci 197762306a36Sopenharmony_ci/* Check if the given lkb conflicts with another lkb on the queue. */ 197862306a36Sopenharmony_ci 197962306a36Sopenharmony_cistatic int queue_conflict(struct list_head *head, struct dlm_lkb *lkb) 198062306a36Sopenharmony_ci{ 198162306a36Sopenharmony_ci struct dlm_lkb *this; 198262306a36Sopenharmony_ci 198362306a36Sopenharmony_ci list_for_each_entry(this, head, lkb_statequeue) { 198462306a36Sopenharmony_ci if (this == lkb) 198562306a36Sopenharmony_ci continue; 198662306a36Sopenharmony_ci if (!modes_compat(this, lkb)) 198762306a36Sopenharmony_ci return 1; 198862306a36Sopenharmony_ci } 198962306a36Sopenharmony_ci return 0; 199062306a36Sopenharmony_ci} 199162306a36Sopenharmony_ci 199262306a36Sopenharmony_ci/* 199362306a36Sopenharmony_ci * "A conversion deadlock arises with a pair of lock requests in the converting 199462306a36Sopenharmony_ci * queue for one resource. The granted mode of each lock blocks the requested 199562306a36Sopenharmony_ci * mode of the other lock." 199662306a36Sopenharmony_ci * 199762306a36Sopenharmony_ci * Part 2: if the granted mode of lkb is preventing an earlier lkb in the 199862306a36Sopenharmony_ci * convert queue from being granted, then deadlk/demote lkb. 199962306a36Sopenharmony_ci * 200062306a36Sopenharmony_ci * Example: 200162306a36Sopenharmony_ci * Granted Queue: empty 200262306a36Sopenharmony_ci * Convert Queue: NL->EX (first lock) 200362306a36Sopenharmony_ci * PR->EX (second lock) 200462306a36Sopenharmony_ci * 200562306a36Sopenharmony_ci * The first lock can't be granted because of the granted mode of the second 200662306a36Sopenharmony_ci * lock and the second lock can't be granted because it's not first in the 200762306a36Sopenharmony_ci * list. We either cancel lkb's conversion (PR->EX) and return EDEADLK, or we 200862306a36Sopenharmony_ci * demote the granted mode of lkb (from PR to NL) if it has the CONVDEADLK 200962306a36Sopenharmony_ci * flag set and return DEMOTED in the lksb flags. 201062306a36Sopenharmony_ci * 201162306a36Sopenharmony_ci * Originally, this function detected conv-deadlk in a more limited scope: 201262306a36Sopenharmony_ci * - if !modes_compat(lkb1, lkb2) && !modes_compat(lkb2, lkb1), or 201362306a36Sopenharmony_ci * - if lkb1 was the first entry in the queue (not just earlier), and was 201462306a36Sopenharmony_ci * blocked by the granted mode of lkb2, and there was nothing on the 201562306a36Sopenharmony_ci * granted queue preventing lkb1 from being granted immediately, i.e. 201662306a36Sopenharmony_ci * lkb2 was the only thing preventing lkb1 from being granted. 201762306a36Sopenharmony_ci * 201862306a36Sopenharmony_ci * That second condition meant we'd only say there was conv-deadlk if 201962306a36Sopenharmony_ci * resolving it (by demotion) would lead to the first lock on the convert 202062306a36Sopenharmony_ci * queue being granted right away. It allowed conversion deadlocks to exist 202162306a36Sopenharmony_ci * between locks on the convert queue while they couldn't be granted anyway. 202262306a36Sopenharmony_ci * 202362306a36Sopenharmony_ci * Now, we detect and take action on conversion deadlocks immediately when 202462306a36Sopenharmony_ci * they're created, even if they may not be immediately consequential. If 202562306a36Sopenharmony_ci * lkb1 exists anywhere in the convert queue and lkb2 comes in with a granted 202662306a36Sopenharmony_ci * mode that would prevent lkb1's conversion from being granted, we do a 202762306a36Sopenharmony_ci * deadlk/demote on lkb2 right away and don't let it onto the convert queue. 202862306a36Sopenharmony_ci * I think this means that the lkb_is_ahead condition below should always 202962306a36Sopenharmony_ci * be zero, i.e. there will never be conv-deadlk between two locks that are 203062306a36Sopenharmony_ci * both already on the convert queue. 203162306a36Sopenharmony_ci */ 203262306a36Sopenharmony_ci 203362306a36Sopenharmony_cistatic int conversion_deadlock_detect(struct dlm_rsb *r, struct dlm_lkb *lkb2) 203462306a36Sopenharmony_ci{ 203562306a36Sopenharmony_ci struct dlm_lkb *lkb1; 203662306a36Sopenharmony_ci int lkb_is_ahead = 0; 203762306a36Sopenharmony_ci 203862306a36Sopenharmony_ci list_for_each_entry(lkb1, &r->res_convertqueue, lkb_statequeue) { 203962306a36Sopenharmony_ci if (lkb1 == lkb2) { 204062306a36Sopenharmony_ci lkb_is_ahead = 1; 204162306a36Sopenharmony_ci continue; 204262306a36Sopenharmony_ci } 204362306a36Sopenharmony_ci 204462306a36Sopenharmony_ci if (!lkb_is_ahead) { 204562306a36Sopenharmony_ci if (!modes_compat(lkb2, lkb1)) 204662306a36Sopenharmony_ci return 1; 204762306a36Sopenharmony_ci } else { 204862306a36Sopenharmony_ci if (!modes_compat(lkb2, lkb1) && 204962306a36Sopenharmony_ci !modes_compat(lkb1, lkb2)) 205062306a36Sopenharmony_ci return 1; 205162306a36Sopenharmony_ci } 205262306a36Sopenharmony_ci } 205362306a36Sopenharmony_ci return 0; 205462306a36Sopenharmony_ci} 205562306a36Sopenharmony_ci 205662306a36Sopenharmony_ci/* 205762306a36Sopenharmony_ci * Return 1 if the lock can be granted, 0 otherwise. 205862306a36Sopenharmony_ci * Also detect and resolve conversion deadlocks. 205962306a36Sopenharmony_ci * 206062306a36Sopenharmony_ci * lkb is the lock to be granted 206162306a36Sopenharmony_ci * 206262306a36Sopenharmony_ci * now is 1 if the function is being called in the context of the 206362306a36Sopenharmony_ci * immediate request, it is 0 if called later, after the lock has been 206462306a36Sopenharmony_ci * queued. 206562306a36Sopenharmony_ci * 206662306a36Sopenharmony_ci * recover is 1 if dlm_recover_grant() is trying to grant conversions 206762306a36Sopenharmony_ci * after recovery. 206862306a36Sopenharmony_ci * 206962306a36Sopenharmony_ci * References are from chapter 6 of "VAXcluster Principles" by Roy Davis 207062306a36Sopenharmony_ci */ 207162306a36Sopenharmony_ci 207262306a36Sopenharmony_cistatic int _can_be_granted(struct dlm_rsb *r, struct dlm_lkb *lkb, int now, 207362306a36Sopenharmony_ci int recover) 207462306a36Sopenharmony_ci{ 207562306a36Sopenharmony_ci int8_t conv = (lkb->lkb_grmode != DLM_LOCK_IV); 207662306a36Sopenharmony_ci 207762306a36Sopenharmony_ci /* 207862306a36Sopenharmony_ci * 6-10: Version 5.4 introduced an option to address the phenomenon of 207962306a36Sopenharmony_ci * a new request for a NL mode lock being blocked. 208062306a36Sopenharmony_ci * 208162306a36Sopenharmony_ci * 6-11: If the optional EXPEDITE flag is used with the new NL mode 208262306a36Sopenharmony_ci * request, then it would be granted. In essence, the use of this flag 208362306a36Sopenharmony_ci * tells the Lock Manager to expedite theis request by not considering 208462306a36Sopenharmony_ci * what may be in the CONVERTING or WAITING queues... As of this 208562306a36Sopenharmony_ci * writing, the EXPEDITE flag can be used only with new requests for NL 208662306a36Sopenharmony_ci * mode locks. This flag is not valid for conversion requests. 208762306a36Sopenharmony_ci * 208862306a36Sopenharmony_ci * A shortcut. Earlier checks return an error if EXPEDITE is used in a 208962306a36Sopenharmony_ci * conversion or used with a non-NL requested mode. We also know an 209062306a36Sopenharmony_ci * EXPEDITE request is always granted immediately, so now must always 209162306a36Sopenharmony_ci * be 1. The full condition to grant an expedite request: (now && 209262306a36Sopenharmony_ci * !conv && lkb->rqmode == DLM_LOCK_NL && (flags & EXPEDITE)) can 209362306a36Sopenharmony_ci * therefore be shortened to just checking the flag. 209462306a36Sopenharmony_ci */ 209562306a36Sopenharmony_ci 209662306a36Sopenharmony_ci if (lkb->lkb_exflags & DLM_LKF_EXPEDITE) 209762306a36Sopenharmony_ci return 1; 209862306a36Sopenharmony_ci 209962306a36Sopenharmony_ci /* 210062306a36Sopenharmony_ci * A shortcut. Without this, !queue_conflict(grantqueue, lkb) would be 210162306a36Sopenharmony_ci * added to the remaining conditions. 210262306a36Sopenharmony_ci */ 210362306a36Sopenharmony_ci 210462306a36Sopenharmony_ci if (queue_conflict(&r->res_grantqueue, lkb)) 210562306a36Sopenharmony_ci return 0; 210662306a36Sopenharmony_ci 210762306a36Sopenharmony_ci /* 210862306a36Sopenharmony_ci * 6-3: By default, a conversion request is immediately granted if the 210962306a36Sopenharmony_ci * requested mode is compatible with the modes of all other granted 211062306a36Sopenharmony_ci * locks 211162306a36Sopenharmony_ci */ 211262306a36Sopenharmony_ci 211362306a36Sopenharmony_ci if (queue_conflict(&r->res_convertqueue, lkb)) 211462306a36Sopenharmony_ci return 0; 211562306a36Sopenharmony_ci 211662306a36Sopenharmony_ci /* 211762306a36Sopenharmony_ci * The RECOVER_GRANT flag means dlm_recover_grant() is granting 211862306a36Sopenharmony_ci * locks for a recovered rsb, on which lkb's have been rebuilt. 211962306a36Sopenharmony_ci * The lkb's may have been rebuilt on the queues in a different 212062306a36Sopenharmony_ci * order than they were in on the previous master. So, granting 212162306a36Sopenharmony_ci * queued conversions in order after recovery doesn't make sense 212262306a36Sopenharmony_ci * since the order hasn't been preserved anyway. The new order 212362306a36Sopenharmony_ci * could also have created a new "in place" conversion deadlock. 212462306a36Sopenharmony_ci * (e.g. old, failed master held granted EX, with PR->EX, NL->EX. 212562306a36Sopenharmony_ci * After recovery, there would be no granted locks, and possibly 212662306a36Sopenharmony_ci * NL->EX, PR->EX, an in-place conversion deadlock.) So, after 212762306a36Sopenharmony_ci * recovery, grant conversions without considering order. 212862306a36Sopenharmony_ci */ 212962306a36Sopenharmony_ci 213062306a36Sopenharmony_ci if (conv && recover) 213162306a36Sopenharmony_ci return 1; 213262306a36Sopenharmony_ci 213362306a36Sopenharmony_ci /* 213462306a36Sopenharmony_ci * 6-5: But the default algorithm for deciding whether to grant or 213562306a36Sopenharmony_ci * queue conversion requests does not by itself guarantee that such 213662306a36Sopenharmony_ci * requests are serviced on a "first come first serve" basis. This, in 213762306a36Sopenharmony_ci * turn, can lead to a phenomenon known as "indefinate postponement". 213862306a36Sopenharmony_ci * 213962306a36Sopenharmony_ci * 6-7: This issue is dealt with by using the optional QUECVT flag with 214062306a36Sopenharmony_ci * the system service employed to request a lock conversion. This flag 214162306a36Sopenharmony_ci * forces certain conversion requests to be queued, even if they are 214262306a36Sopenharmony_ci * compatible with the granted modes of other locks on the same 214362306a36Sopenharmony_ci * resource. Thus, the use of this flag results in conversion requests 214462306a36Sopenharmony_ci * being ordered on a "first come first servce" basis. 214562306a36Sopenharmony_ci * 214662306a36Sopenharmony_ci * DCT: This condition is all about new conversions being able to occur 214762306a36Sopenharmony_ci * "in place" while the lock remains on the granted queue (assuming 214862306a36Sopenharmony_ci * nothing else conflicts.) IOW if QUECVT isn't set, a conversion 214962306a36Sopenharmony_ci * doesn't _have_ to go onto the convert queue where it's processed in 215062306a36Sopenharmony_ci * order. The "now" variable is necessary to distinguish converts 215162306a36Sopenharmony_ci * being received and processed for the first time now, because once a 215262306a36Sopenharmony_ci * convert is moved to the conversion queue the condition below applies 215362306a36Sopenharmony_ci * requiring fifo granting. 215462306a36Sopenharmony_ci */ 215562306a36Sopenharmony_ci 215662306a36Sopenharmony_ci if (now && conv && !(lkb->lkb_exflags & DLM_LKF_QUECVT)) 215762306a36Sopenharmony_ci return 1; 215862306a36Sopenharmony_ci 215962306a36Sopenharmony_ci /* 216062306a36Sopenharmony_ci * Even if the convert is compat with all granted locks, 216162306a36Sopenharmony_ci * QUECVT forces it behind other locks on the convert queue. 216262306a36Sopenharmony_ci */ 216362306a36Sopenharmony_ci 216462306a36Sopenharmony_ci if (now && conv && (lkb->lkb_exflags & DLM_LKF_QUECVT)) { 216562306a36Sopenharmony_ci if (list_empty(&r->res_convertqueue)) 216662306a36Sopenharmony_ci return 1; 216762306a36Sopenharmony_ci else 216862306a36Sopenharmony_ci return 0; 216962306a36Sopenharmony_ci } 217062306a36Sopenharmony_ci 217162306a36Sopenharmony_ci /* 217262306a36Sopenharmony_ci * The NOORDER flag is set to avoid the standard vms rules on grant 217362306a36Sopenharmony_ci * order. 217462306a36Sopenharmony_ci */ 217562306a36Sopenharmony_ci 217662306a36Sopenharmony_ci if (lkb->lkb_exflags & DLM_LKF_NOORDER) 217762306a36Sopenharmony_ci return 1; 217862306a36Sopenharmony_ci 217962306a36Sopenharmony_ci /* 218062306a36Sopenharmony_ci * 6-3: Once in that queue [CONVERTING], a conversion request cannot be 218162306a36Sopenharmony_ci * granted until all other conversion requests ahead of it are granted 218262306a36Sopenharmony_ci * and/or canceled. 218362306a36Sopenharmony_ci */ 218462306a36Sopenharmony_ci 218562306a36Sopenharmony_ci if (!now && conv && first_in_list(lkb, &r->res_convertqueue)) 218662306a36Sopenharmony_ci return 1; 218762306a36Sopenharmony_ci 218862306a36Sopenharmony_ci /* 218962306a36Sopenharmony_ci * 6-4: By default, a new request is immediately granted only if all 219062306a36Sopenharmony_ci * three of the following conditions are satisfied when the request is 219162306a36Sopenharmony_ci * issued: 219262306a36Sopenharmony_ci * - The queue of ungranted conversion requests for the resource is 219362306a36Sopenharmony_ci * empty. 219462306a36Sopenharmony_ci * - The queue of ungranted new requests for the resource is empty. 219562306a36Sopenharmony_ci * - The mode of the new request is compatible with the most 219662306a36Sopenharmony_ci * restrictive mode of all granted locks on the resource. 219762306a36Sopenharmony_ci */ 219862306a36Sopenharmony_ci 219962306a36Sopenharmony_ci if (now && !conv && list_empty(&r->res_convertqueue) && 220062306a36Sopenharmony_ci list_empty(&r->res_waitqueue)) 220162306a36Sopenharmony_ci return 1; 220262306a36Sopenharmony_ci 220362306a36Sopenharmony_ci /* 220462306a36Sopenharmony_ci * 6-4: Once a lock request is in the queue of ungranted new requests, 220562306a36Sopenharmony_ci * it cannot be granted until the queue of ungranted conversion 220662306a36Sopenharmony_ci * requests is empty, all ungranted new requests ahead of it are 220762306a36Sopenharmony_ci * granted and/or canceled, and it is compatible with the granted mode 220862306a36Sopenharmony_ci * of the most restrictive lock granted on the resource. 220962306a36Sopenharmony_ci */ 221062306a36Sopenharmony_ci 221162306a36Sopenharmony_ci if (!now && !conv && list_empty(&r->res_convertqueue) && 221262306a36Sopenharmony_ci first_in_list(lkb, &r->res_waitqueue)) 221362306a36Sopenharmony_ci return 1; 221462306a36Sopenharmony_ci 221562306a36Sopenharmony_ci return 0; 221662306a36Sopenharmony_ci} 221762306a36Sopenharmony_ci 221862306a36Sopenharmony_cistatic int can_be_granted(struct dlm_rsb *r, struct dlm_lkb *lkb, int now, 221962306a36Sopenharmony_ci int recover, int *err) 222062306a36Sopenharmony_ci{ 222162306a36Sopenharmony_ci int rv; 222262306a36Sopenharmony_ci int8_t alt = 0, rqmode = lkb->lkb_rqmode; 222362306a36Sopenharmony_ci int8_t is_convert = (lkb->lkb_grmode != DLM_LOCK_IV); 222462306a36Sopenharmony_ci 222562306a36Sopenharmony_ci if (err) 222662306a36Sopenharmony_ci *err = 0; 222762306a36Sopenharmony_ci 222862306a36Sopenharmony_ci rv = _can_be_granted(r, lkb, now, recover); 222962306a36Sopenharmony_ci if (rv) 223062306a36Sopenharmony_ci goto out; 223162306a36Sopenharmony_ci 223262306a36Sopenharmony_ci /* 223362306a36Sopenharmony_ci * The CONVDEADLK flag is non-standard and tells the dlm to resolve 223462306a36Sopenharmony_ci * conversion deadlocks by demoting grmode to NL, otherwise the dlm 223562306a36Sopenharmony_ci * cancels one of the locks. 223662306a36Sopenharmony_ci */ 223762306a36Sopenharmony_ci 223862306a36Sopenharmony_ci if (is_convert && can_be_queued(lkb) && 223962306a36Sopenharmony_ci conversion_deadlock_detect(r, lkb)) { 224062306a36Sopenharmony_ci if (lkb->lkb_exflags & DLM_LKF_CONVDEADLK) { 224162306a36Sopenharmony_ci lkb->lkb_grmode = DLM_LOCK_NL; 224262306a36Sopenharmony_ci set_bit(DLM_SBF_DEMOTED_BIT, &lkb->lkb_sbflags); 224362306a36Sopenharmony_ci } else if (err) { 224462306a36Sopenharmony_ci *err = -EDEADLK; 224562306a36Sopenharmony_ci } else { 224662306a36Sopenharmony_ci log_print("can_be_granted deadlock %x now %d", 224762306a36Sopenharmony_ci lkb->lkb_id, now); 224862306a36Sopenharmony_ci dlm_dump_rsb(r); 224962306a36Sopenharmony_ci } 225062306a36Sopenharmony_ci goto out; 225162306a36Sopenharmony_ci } 225262306a36Sopenharmony_ci 225362306a36Sopenharmony_ci /* 225462306a36Sopenharmony_ci * The ALTPR and ALTCW flags are non-standard and tell the dlm to try 225562306a36Sopenharmony_ci * to grant a request in a mode other than the normal rqmode. It's a 225662306a36Sopenharmony_ci * simple way to provide a big optimization to applications that can 225762306a36Sopenharmony_ci * use them. 225862306a36Sopenharmony_ci */ 225962306a36Sopenharmony_ci 226062306a36Sopenharmony_ci if (rqmode != DLM_LOCK_PR && (lkb->lkb_exflags & DLM_LKF_ALTPR)) 226162306a36Sopenharmony_ci alt = DLM_LOCK_PR; 226262306a36Sopenharmony_ci else if (rqmode != DLM_LOCK_CW && (lkb->lkb_exflags & DLM_LKF_ALTCW)) 226362306a36Sopenharmony_ci alt = DLM_LOCK_CW; 226462306a36Sopenharmony_ci 226562306a36Sopenharmony_ci if (alt) { 226662306a36Sopenharmony_ci lkb->lkb_rqmode = alt; 226762306a36Sopenharmony_ci rv = _can_be_granted(r, lkb, now, 0); 226862306a36Sopenharmony_ci if (rv) 226962306a36Sopenharmony_ci set_bit(DLM_SBF_ALTMODE_BIT, &lkb->lkb_sbflags); 227062306a36Sopenharmony_ci else 227162306a36Sopenharmony_ci lkb->lkb_rqmode = rqmode; 227262306a36Sopenharmony_ci } 227362306a36Sopenharmony_ci out: 227462306a36Sopenharmony_ci return rv; 227562306a36Sopenharmony_ci} 227662306a36Sopenharmony_ci 227762306a36Sopenharmony_ci/* Returns the highest requested mode of all blocked conversions; sets 227862306a36Sopenharmony_ci cw if there's a blocked conversion to DLM_LOCK_CW. */ 227962306a36Sopenharmony_ci 228062306a36Sopenharmony_cistatic int grant_pending_convert(struct dlm_rsb *r, int high, int *cw, 228162306a36Sopenharmony_ci unsigned int *count) 228262306a36Sopenharmony_ci{ 228362306a36Sopenharmony_ci struct dlm_lkb *lkb, *s; 228462306a36Sopenharmony_ci int recover = rsb_flag(r, RSB_RECOVER_GRANT); 228562306a36Sopenharmony_ci int hi, demoted, quit, grant_restart, demote_restart; 228662306a36Sopenharmony_ci int deadlk; 228762306a36Sopenharmony_ci 228862306a36Sopenharmony_ci quit = 0; 228962306a36Sopenharmony_ci restart: 229062306a36Sopenharmony_ci grant_restart = 0; 229162306a36Sopenharmony_ci demote_restart = 0; 229262306a36Sopenharmony_ci hi = DLM_LOCK_IV; 229362306a36Sopenharmony_ci 229462306a36Sopenharmony_ci list_for_each_entry_safe(lkb, s, &r->res_convertqueue, lkb_statequeue) { 229562306a36Sopenharmony_ci demoted = is_demoted(lkb); 229662306a36Sopenharmony_ci deadlk = 0; 229762306a36Sopenharmony_ci 229862306a36Sopenharmony_ci if (can_be_granted(r, lkb, 0, recover, &deadlk)) { 229962306a36Sopenharmony_ci grant_lock_pending(r, lkb); 230062306a36Sopenharmony_ci grant_restart = 1; 230162306a36Sopenharmony_ci if (count) 230262306a36Sopenharmony_ci (*count)++; 230362306a36Sopenharmony_ci continue; 230462306a36Sopenharmony_ci } 230562306a36Sopenharmony_ci 230662306a36Sopenharmony_ci if (!demoted && is_demoted(lkb)) { 230762306a36Sopenharmony_ci log_print("WARN: pending demoted %x node %d %s", 230862306a36Sopenharmony_ci lkb->lkb_id, lkb->lkb_nodeid, r->res_name); 230962306a36Sopenharmony_ci demote_restart = 1; 231062306a36Sopenharmony_ci continue; 231162306a36Sopenharmony_ci } 231262306a36Sopenharmony_ci 231362306a36Sopenharmony_ci if (deadlk) { 231462306a36Sopenharmony_ci /* 231562306a36Sopenharmony_ci * If DLM_LKB_NODLKWT flag is set and conversion 231662306a36Sopenharmony_ci * deadlock is detected, we request blocking AST and 231762306a36Sopenharmony_ci * down (or cancel) conversion. 231862306a36Sopenharmony_ci */ 231962306a36Sopenharmony_ci if (lkb->lkb_exflags & DLM_LKF_NODLCKWT) { 232062306a36Sopenharmony_ci if (lkb->lkb_highbast < lkb->lkb_rqmode) { 232162306a36Sopenharmony_ci queue_bast(r, lkb, lkb->lkb_rqmode); 232262306a36Sopenharmony_ci lkb->lkb_highbast = lkb->lkb_rqmode; 232362306a36Sopenharmony_ci } 232462306a36Sopenharmony_ci } else { 232562306a36Sopenharmony_ci log_print("WARN: pending deadlock %x node %d %s", 232662306a36Sopenharmony_ci lkb->lkb_id, lkb->lkb_nodeid, 232762306a36Sopenharmony_ci r->res_name); 232862306a36Sopenharmony_ci dlm_dump_rsb(r); 232962306a36Sopenharmony_ci } 233062306a36Sopenharmony_ci continue; 233162306a36Sopenharmony_ci } 233262306a36Sopenharmony_ci 233362306a36Sopenharmony_ci hi = max_t(int, lkb->lkb_rqmode, hi); 233462306a36Sopenharmony_ci 233562306a36Sopenharmony_ci if (cw && lkb->lkb_rqmode == DLM_LOCK_CW) 233662306a36Sopenharmony_ci *cw = 1; 233762306a36Sopenharmony_ci } 233862306a36Sopenharmony_ci 233962306a36Sopenharmony_ci if (grant_restart) 234062306a36Sopenharmony_ci goto restart; 234162306a36Sopenharmony_ci if (demote_restart && !quit) { 234262306a36Sopenharmony_ci quit = 1; 234362306a36Sopenharmony_ci goto restart; 234462306a36Sopenharmony_ci } 234562306a36Sopenharmony_ci 234662306a36Sopenharmony_ci return max_t(int, high, hi); 234762306a36Sopenharmony_ci} 234862306a36Sopenharmony_ci 234962306a36Sopenharmony_cistatic int grant_pending_wait(struct dlm_rsb *r, int high, int *cw, 235062306a36Sopenharmony_ci unsigned int *count) 235162306a36Sopenharmony_ci{ 235262306a36Sopenharmony_ci struct dlm_lkb *lkb, *s; 235362306a36Sopenharmony_ci 235462306a36Sopenharmony_ci list_for_each_entry_safe(lkb, s, &r->res_waitqueue, lkb_statequeue) { 235562306a36Sopenharmony_ci if (can_be_granted(r, lkb, 0, 0, NULL)) { 235662306a36Sopenharmony_ci grant_lock_pending(r, lkb); 235762306a36Sopenharmony_ci if (count) 235862306a36Sopenharmony_ci (*count)++; 235962306a36Sopenharmony_ci } else { 236062306a36Sopenharmony_ci high = max_t(int, lkb->lkb_rqmode, high); 236162306a36Sopenharmony_ci if (lkb->lkb_rqmode == DLM_LOCK_CW) 236262306a36Sopenharmony_ci *cw = 1; 236362306a36Sopenharmony_ci } 236462306a36Sopenharmony_ci } 236562306a36Sopenharmony_ci 236662306a36Sopenharmony_ci return high; 236762306a36Sopenharmony_ci} 236862306a36Sopenharmony_ci 236962306a36Sopenharmony_ci/* cw of 1 means there's a lock with a rqmode of DLM_LOCK_CW that's blocked 237062306a36Sopenharmony_ci on either the convert or waiting queue. 237162306a36Sopenharmony_ci high is the largest rqmode of all locks blocked on the convert or 237262306a36Sopenharmony_ci waiting queue. */ 237362306a36Sopenharmony_ci 237462306a36Sopenharmony_cistatic int lock_requires_bast(struct dlm_lkb *gr, int high, int cw) 237562306a36Sopenharmony_ci{ 237662306a36Sopenharmony_ci if (gr->lkb_grmode == DLM_LOCK_PR && cw) { 237762306a36Sopenharmony_ci if (gr->lkb_highbast < DLM_LOCK_EX) 237862306a36Sopenharmony_ci return 1; 237962306a36Sopenharmony_ci return 0; 238062306a36Sopenharmony_ci } 238162306a36Sopenharmony_ci 238262306a36Sopenharmony_ci if (gr->lkb_highbast < high && 238362306a36Sopenharmony_ci !__dlm_compat_matrix[gr->lkb_grmode+1][high+1]) 238462306a36Sopenharmony_ci return 1; 238562306a36Sopenharmony_ci return 0; 238662306a36Sopenharmony_ci} 238762306a36Sopenharmony_ci 238862306a36Sopenharmony_cistatic void grant_pending_locks(struct dlm_rsb *r, unsigned int *count) 238962306a36Sopenharmony_ci{ 239062306a36Sopenharmony_ci struct dlm_lkb *lkb, *s; 239162306a36Sopenharmony_ci int high = DLM_LOCK_IV; 239262306a36Sopenharmony_ci int cw = 0; 239362306a36Sopenharmony_ci 239462306a36Sopenharmony_ci if (!is_master(r)) { 239562306a36Sopenharmony_ci log_print("grant_pending_locks r nodeid %d", r->res_nodeid); 239662306a36Sopenharmony_ci dlm_dump_rsb(r); 239762306a36Sopenharmony_ci return; 239862306a36Sopenharmony_ci } 239962306a36Sopenharmony_ci 240062306a36Sopenharmony_ci high = grant_pending_convert(r, high, &cw, count); 240162306a36Sopenharmony_ci high = grant_pending_wait(r, high, &cw, count); 240262306a36Sopenharmony_ci 240362306a36Sopenharmony_ci if (high == DLM_LOCK_IV) 240462306a36Sopenharmony_ci return; 240562306a36Sopenharmony_ci 240662306a36Sopenharmony_ci /* 240762306a36Sopenharmony_ci * If there are locks left on the wait/convert queue then send blocking 240862306a36Sopenharmony_ci * ASTs to granted locks based on the largest requested mode (high) 240962306a36Sopenharmony_ci * found above. 241062306a36Sopenharmony_ci */ 241162306a36Sopenharmony_ci 241262306a36Sopenharmony_ci list_for_each_entry_safe(lkb, s, &r->res_grantqueue, lkb_statequeue) { 241362306a36Sopenharmony_ci if (lkb->lkb_bastfn && lock_requires_bast(lkb, high, cw)) { 241462306a36Sopenharmony_ci if (cw && high == DLM_LOCK_PR && 241562306a36Sopenharmony_ci lkb->lkb_grmode == DLM_LOCK_PR) 241662306a36Sopenharmony_ci queue_bast(r, lkb, DLM_LOCK_CW); 241762306a36Sopenharmony_ci else 241862306a36Sopenharmony_ci queue_bast(r, lkb, high); 241962306a36Sopenharmony_ci lkb->lkb_highbast = high; 242062306a36Sopenharmony_ci } 242162306a36Sopenharmony_ci } 242262306a36Sopenharmony_ci} 242362306a36Sopenharmony_ci 242462306a36Sopenharmony_cistatic int modes_require_bast(struct dlm_lkb *gr, struct dlm_lkb *rq) 242562306a36Sopenharmony_ci{ 242662306a36Sopenharmony_ci if ((gr->lkb_grmode == DLM_LOCK_PR && rq->lkb_rqmode == DLM_LOCK_CW) || 242762306a36Sopenharmony_ci (gr->lkb_grmode == DLM_LOCK_CW && rq->lkb_rqmode == DLM_LOCK_PR)) { 242862306a36Sopenharmony_ci if (gr->lkb_highbast < DLM_LOCK_EX) 242962306a36Sopenharmony_ci return 1; 243062306a36Sopenharmony_ci return 0; 243162306a36Sopenharmony_ci } 243262306a36Sopenharmony_ci 243362306a36Sopenharmony_ci if (gr->lkb_highbast < rq->lkb_rqmode && !modes_compat(gr, rq)) 243462306a36Sopenharmony_ci return 1; 243562306a36Sopenharmony_ci return 0; 243662306a36Sopenharmony_ci} 243762306a36Sopenharmony_ci 243862306a36Sopenharmony_cistatic void send_bast_queue(struct dlm_rsb *r, struct list_head *head, 243962306a36Sopenharmony_ci struct dlm_lkb *lkb) 244062306a36Sopenharmony_ci{ 244162306a36Sopenharmony_ci struct dlm_lkb *gr; 244262306a36Sopenharmony_ci 244362306a36Sopenharmony_ci list_for_each_entry(gr, head, lkb_statequeue) { 244462306a36Sopenharmony_ci /* skip self when sending basts to convertqueue */ 244562306a36Sopenharmony_ci if (gr == lkb) 244662306a36Sopenharmony_ci continue; 244762306a36Sopenharmony_ci if (gr->lkb_bastfn && modes_require_bast(gr, lkb)) { 244862306a36Sopenharmony_ci queue_bast(r, gr, lkb->lkb_rqmode); 244962306a36Sopenharmony_ci gr->lkb_highbast = lkb->lkb_rqmode; 245062306a36Sopenharmony_ci } 245162306a36Sopenharmony_ci } 245262306a36Sopenharmony_ci} 245362306a36Sopenharmony_ci 245462306a36Sopenharmony_cistatic void send_blocking_asts(struct dlm_rsb *r, struct dlm_lkb *lkb) 245562306a36Sopenharmony_ci{ 245662306a36Sopenharmony_ci send_bast_queue(r, &r->res_grantqueue, lkb); 245762306a36Sopenharmony_ci} 245862306a36Sopenharmony_ci 245962306a36Sopenharmony_cistatic void send_blocking_asts_all(struct dlm_rsb *r, struct dlm_lkb *lkb) 246062306a36Sopenharmony_ci{ 246162306a36Sopenharmony_ci send_bast_queue(r, &r->res_grantqueue, lkb); 246262306a36Sopenharmony_ci send_bast_queue(r, &r->res_convertqueue, lkb); 246362306a36Sopenharmony_ci} 246462306a36Sopenharmony_ci 246562306a36Sopenharmony_ci/* set_master(r, lkb) -- set the master nodeid of a resource 246662306a36Sopenharmony_ci 246762306a36Sopenharmony_ci The purpose of this function is to set the nodeid field in the given 246862306a36Sopenharmony_ci lkb using the nodeid field in the given rsb. If the rsb's nodeid is 246962306a36Sopenharmony_ci known, it can just be copied to the lkb and the function will return 247062306a36Sopenharmony_ci 0. If the rsb's nodeid is _not_ known, it needs to be looked up 247162306a36Sopenharmony_ci before it can be copied to the lkb. 247262306a36Sopenharmony_ci 247362306a36Sopenharmony_ci When the rsb nodeid is being looked up remotely, the initial lkb 247462306a36Sopenharmony_ci causing the lookup is kept on the ls_waiters list waiting for the 247562306a36Sopenharmony_ci lookup reply. Other lkb's waiting for the same rsb lookup are kept 247662306a36Sopenharmony_ci on the rsb's res_lookup list until the master is verified. 247762306a36Sopenharmony_ci 247862306a36Sopenharmony_ci Return values: 247962306a36Sopenharmony_ci 0: nodeid is set in rsb/lkb and the caller should go ahead and use it 248062306a36Sopenharmony_ci 1: the rsb master is not available and the lkb has been placed on 248162306a36Sopenharmony_ci a wait queue 248262306a36Sopenharmony_ci*/ 248362306a36Sopenharmony_ci 248462306a36Sopenharmony_cistatic int set_master(struct dlm_rsb *r, struct dlm_lkb *lkb) 248562306a36Sopenharmony_ci{ 248662306a36Sopenharmony_ci int our_nodeid = dlm_our_nodeid(); 248762306a36Sopenharmony_ci 248862306a36Sopenharmony_ci if (rsb_flag(r, RSB_MASTER_UNCERTAIN)) { 248962306a36Sopenharmony_ci rsb_clear_flag(r, RSB_MASTER_UNCERTAIN); 249062306a36Sopenharmony_ci r->res_first_lkid = lkb->lkb_id; 249162306a36Sopenharmony_ci lkb->lkb_nodeid = r->res_nodeid; 249262306a36Sopenharmony_ci return 0; 249362306a36Sopenharmony_ci } 249462306a36Sopenharmony_ci 249562306a36Sopenharmony_ci if (r->res_first_lkid && r->res_first_lkid != lkb->lkb_id) { 249662306a36Sopenharmony_ci list_add_tail(&lkb->lkb_rsb_lookup, &r->res_lookup); 249762306a36Sopenharmony_ci return 1; 249862306a36Sopenharmony_ci } 249962306a36Sopenharmony_ci 250062306a36Sopenharmony_ci if (r->res_master_nodeid == our_nodeid) { 250162306a36Sopenharmony_ci lkb->lkb_nodeid = 0; 250262306a36Sopenharmony_ci return 0; 250362306a36Sopenharmony_ci } 250462306a36Sopenharmony_ci 250562306a36Sopenharmony_ci if (r->res_master_nodeid) { 250662306a36Sopenharmony_ci lkb->lkb_nodeid = r->res_master_nodeid; 250762306a36Sopenharmony_ci return 0; 250862306a36Sopenharmony_ci } 250962306a36Sopenharmony_ci 251062306a36Sopenharmony_ci if (dlm_dir_nodeid(r) == our_nodeid) { 251162306a36Sopenharmony_ci /* This is a somewhat unusual case; find_rsb will usually 251262306a36Sopenharmony_ci have set res_master_nodeid when dir nodeid is local, but 251362306a36Sopenharmony_ci there are cases where we become the dir node after we've 251462306a36Sopenharmony_ci past find_rsb and go through _request_lock again. 251562306a36Sopenharmony_ci confirm_master() or process_lookup_list() needs to be 251662306a36Sopenharmony_ci called after this. */ 251762306a36Sopenharmony_ci log_debug(r->res_ls, "set_master %x self master %d dir %d %s", 251862306a36Sopenharmony_ci lkb->lkb_id, r->res_master_nodeid, r->res_dir_nodeid, 251962306a36Sopenharmony_ci r->res_name); 252062306a36Sopenharmony_ci r->res_master_nodeid = our_nodeid; 252162306a36Sopenharmony_ci r->res_nodeid = 0; 252262306a36Sopenharmony_ci lkb->lkb_nodeid = 0; 252362306a36Sopenharmony_ci return 0; 252462306a36Sopenharmony_ci } 252562306a36Sopenharmony_ci 252662306a36Sopenharmony_ci r->res_first_lkid = lkb->lkb_id; 252762306a36Sopenharmony_ci send_lookup(r, lkb); 252862306a36Sopenharmony_ci return 1; 252962306a36Sopenharmony_ci} 253062306a36Sopenharmony_ci 253162306a36Sopenharmony_cistatic void process_lookup_list(struct dlm_rsb *r) 253262306a36Sopenharmony_ci{ 253362306a36Sopenharmony_ci struct dlm_lkb *lkb, *safe; 253462306a36Sopenharmony_ci 253562306a36Sopenharmony_ci list_for_each_entry_safe(lkb, safe, &r->res_lookup, lkb_rsb_lookup) { 253662306a36Sopenharmony_ci list_del_init(&lkb->lkb_rsb_lookup); 253762306a36Sopenharmony_ci _request_lock(r, lkb); 253862306a36Sopenharmony_ci schedule(); 253962306a36Sopenharmony_ci } 254062306a36Sopenharmony_ci} 254162306a36Sopenharmony_ci 254262306a36Sopenharmony_ci/* confirm_master -- confirm (or deny) an rsb's master nodeid */ 254362306a36Sopenharmony_ci 254462306a36Sopenharmony_cistatic void confirm_master(struct dlm_rsb *r, int error) 254562306a36Sopenharmony_ci{ 254662306a36Sopenharmony_ci struct dlm_lkb *lkb; 254762306a36Sopenharmony_ci 254862306a36Sopenharmony_ci if (!r->res_first_lkid) 254962306a36Sopenharmony_ci return; 255062306a36Sopenharmony_ci 255162306a36Sopenharmony_ci switch (error) { 255262306a36Sopenharmony_ci case 0: 255362306a36Sopenharmony_ci case -EINPROGRESS: 255462306a36Sopenharmony_ci r->res_first_lkid = 0; 255562306a36Sopenharmony_ci process_lookup_list(r); 255662306a36Sopenharmony_ci break; 255762306a36Sopenharmony_ci 255862306a36Sopenharmony_ci case -EAGAIN: 255962306a36Sopenharmony_ci case -EBADR: 256062306a36Sopenharmony_ci case -ENOTBLK: 256162306a36Sopenharmony_ci /* the remote request failed and won't be retried (it was 256262306a36Sopenharmony_ci a NOQUEUE, or has been canceled/unlocked); make a waiting 256362306a36Sopenharmony_ci lkb the first_lkid */ 256462306a36Sopenharmony_ci 256562306a36Sopenharmony_ci r->res_first_lkid = 0; 256662306a36Sopenharmony_ci 256762306a36Sopenharmony_ci if (!list_empty(&r->res_lookup)) { 256862306a36Sopenharmony_ci lkb = list_entry(r->res_lookup.next, struct dlm_lkb, 256962306a36Sopenharmony_ci lkb_rsb_lookup); 257062306a36Sopenharmony_ci list_del_init(&lkb->lkb_rsb_lookup); 257162306a36Sopenharmony_ci r->res_first_lkid = lkb->lkb_id; 257262306a36Sopenharmony_ci _request_lock(r, lkb); 257362306a36Sopenharmony_ci } 257462306a36Sopenharmony_ci break; 257562306a36Sopenharmony_ci 257662306a36Sopenharmony_ci default: 257762306a36Sopenharmony_ci log_error(r->res_ls, "confirm_master unknown error %d", error); 257862306a36Sopenharmony_ci } 257962306a36Sopenharmony_ci} 258062306a36Sopenharmony_ci 258162306a36Sopenharmony_cistatic int set_lock_args(int mode, struct dlm_lksb *lksb, uint32_t flags, 258262306a36Sopenharmony_ci int namelen, void (*ast)(void *astparam), 258362306a36Sopenharmony_ci void *astparam, 258462306a36Sopenharmony_ci void (*bast)(void *astparam, int mode), 258562306a36Sopenharmony_ci struct dlm_args *args) 258662306a36Sopenharmony_ci{ 258762306a36Sopenharmony_ci int rv = -EINVAL; 258862306a36Sopenharmony_ci 258962306a36Sopenharmony_ci /* check for invalid arg usage */ 259062306a36Sopenharmony_ci 259162306a36Sopenharmony_ci if (mode < 0 || mode > DLM_LOCK_EX) 259262306a36Sopenharmony_ci goto out; 259362306a36Sopenharmony_ci 259462306a36Sopenharmony_ci if (!(flags & DLM_LKF_CONVERT) && (namelen > DLM_RESNAME_MAXLEN)) 259562306a36Sopenharmony_ci goto out; 259662306a36Sopenharmony_ci 259762306a36Sopenharmony_ci if (flags & DLM_LKF_CANCEL) 259862306a36Sopenharmony_ci goto out; 259962306a36Sopenharmony_ci 260062306a36Sopenharmony_ci if (flags & DLM_LKF_QUECVT && !(flags & DLM_LKF_CONVERT)) 260162306a36Sopenharmony_ci goto out; 260262306a36Sopenharmony_ci 260362306a36Sopenharmony_ci if (flags & DLM_LKF_CONVDEADLK && !(flags & DLM_LKF_CONVERT)) 260462306a36Sopenharmony_ci goto out; 260562306a36Sopenharmony_ci 260662306a36Sopenharmony_ci if (flags & DLM_LKF_CONVDEADLK && flags & DLM_LKF_NOQUEUE) 260762306a36Sopenharmony_ci goto out; 260862306a36Sopenharmony_ci 260962306a36Sopenharmony_ci if (flags & DLM_LKF_EXPEDITE && flags & DLM_LKF_CONVERT) 261062306a36Sopenharmony_ci goto out; 261162306a36Sopenharmony_ci 261262306a36Sopenharmony_ci if (flags & DLM_LKF_EXPEDITE && flags & DLM_LKF_QUECVT) 261362306a36Sopenharmony_ci goto out; 261462306a36Sopenharmony_ci 261562306a36Sopenharmony_ci if (flags & DLM_LKF_EXPEDITE && flags & DLM_LKF_NOQUEUE) 261662306a36Sopenharmony_ci goto out; 261762306a36Sopenharmony_ci 261862306a36Sopenharmony_ci if (flags & DLM_LKF_EXPEDITE && mode != DLM_LOCK_NL) 261962306a36Sopenharmony_ci goto out; 262062306a36Sopenharmony_ci 262162306a36Sopenharmony_ci if (!ast || !lksb) 262262306a36Sopenharmony_ci goto out; 262362306a36Sopenharmony_ci 262462306a36Sopenharmony_ci if (flags & DLM_LKF_VALBLK && !lksb->sb_lvbptr) 262562306a36Sopenharmony_ci goto out; 262662306a36Sopenharmony_ci 262762306a36Sopenharmony_ci if (flags & DLM_LKF_CONVERT && !lksb->sb_lkid) 262862306a36Sopenharmony_ci goto out; 262962306a36Sopenharmony_ci 263062306a36Sopenharmony_ci /* these args will be copied to the lkb in validate_lock_args, 263162306a36Sopenharmony_ci it cannot be done now because when converting locks, fields in 263262306a36Sopenharmony_ci an active lkb cannot be modified before locking the rsb */ 263362306a36Sopenharmony_ci 263462306a36Sopenharmony_ci args->flags = flags; 263562306a36Sopenharmony_ci args->astfn = ast; 263662306a36Sopenharmony_ci args->astparam = astparam; 263762306a36Sopenharmony_ci args->bastfn = bast; 263862306a36Sopenharmony_ci args->mode = mode; 263962306a36Sopenharmony_ci args->lksb = lksb; 264062306a36Sopenharmony_ci rv = 0; 264162306a36Sopenharmony_ci out: 264262306a36Sopenharmony_ci return rv; 264362306a36Sopenharmony_ci} 264462306a36Sopenharmony_ci 264562306a36Sopenharmony_cistatic int set_unlock_args(uint32_t flags, void *astarg, struct dlm_args *args) 264662306a36Sopenharmony_ci{ 264762306a36Sopenharmony_ci if (flags & ~(DLM_LKF_CANCEL | DLM_LKF_VALBLK | DLM_LKF_IVVALBLK | 264862306a36Sopenharmony_ci DLM_LKF_FORCEUNLOCK)) 264962306a36Sopenharmony_ci return -EINVAL; 265062306a36Sopenharmony_ci 265162306a36Sopenharmony_ci if (flags & DLM_LKF_CANCEL && flags & DLM_LKF_FORCEUNLOCK) 265262306a36Sopenharmony_ci return -EINVAL; 265362306a36Sopenharmony_ci 265462306a36Sopenharmony_ci args->flags = flags; 265562306a36Sopenharmony_ci args->astparam = astarg; 265662306a36Sopenharmony_ci return 0; 265762306a36Sopenharmony_ci} 265862306a36Sopenharmony_ci 265962306a36Sopenharmony_cistatic int validate_lock_args(struct dlm_ls *ls, struct dlm_lkb *lkb, 266062306a36Sopenharmony_ci struct dlm_args *args) 266162306a36Sopenharmony_ci{ 266262306a36Sopenharmony_ci int rv = -EBUSY; 266362306a36Sopenharmony_ci 266462306a36Sopenharmony_ci if (args->flags & DLM_LKF_CONVERT) { 266562306a36Sopenharmony_ci if (lkb->lkb_status != DLM_LKSTS_GRANTED) 266662306a36Sopenharmony_ci goto out; 266762306a36Sopenharmony_ci 266862306a36Sopenharmony_ci /* lock not allowed if there's any op in progress */ 266962306a36Sopenharmony_ci if (lkb->lkb_wait_type || atomic_read(&lkb->lkb_wait_count)) 267062306a36Sopenharmony_ci goto out; 267162306a36Sopenharmony_ci 267262306a36Sopenharmony_ci if (is_overlap(lkb)) 267362306a36Sopenharmony_ci goto out; 267462306a36Sopenharmony_ci 267562306a36Sopenharmony_ci rv = -EINVAL; 267662306a36Sopenharmony_ci if (test_bit(DLM_IFL_MSTCPY_BIT, &lkb->lkb_iflags)) 267762306a36Sopenharmony_ci goto out; 267862306a36Sopenharmony_ci 267962306a36Sopenharmony_ci if (args->flags & DLM_LKF_QUECVT && 268062306a36Sopenharmony_ci !__quecvt_compat_matrix[lkb->lkb_grmode+1][args->mode+1]) 268162306a36Sopenharmony_ci goto out; 268262306a36Sopenharmony_ci } 268362306a36Sopenharmony_ci 268462306a36Sopenharmony_ci lkb->lkb_exflags = args->flags; 268562306a36Sopenharmony_ci dlm_set_sbflags_val(lkb, 0); 268662306a36Sopenharmony_ci lkb->lkb_astfn = args->astfn; 268762306a36Sopenharmony_ci lkb->lkb_astparam = args->astparam; 268862306a36Sopenharmony_ci lkb->lkb_bastfn = args->bastfn; 268962306a36Sopenharmony_ci lkb->lkb_rqmode = args->mode; 269062306a36Sopenharmony_ci lkb->lkb_lksb = args->lksb; 269162306a36Sopenharmony_ci lkb->lkb_lvbptr = args->lksb->sb_lvbptr; 269262306a36Sopenharmony_ci lkb->lkb_ownpid = (int) current->pid; 269362306a36Sopenharmony_ci rv = 0; 269462306a36Sopenharmony_ci out: 269562306a36Sopenharmony_ci switch (rv) { 269662306a36Sopenharmony_ci case 0: 269762306a36Sopenharmony_ci break; 269862306a36Sopenharmony_ci case -EINVAL: 269962306a36Sopenharmony_ci /* annoy the user because dlm usage is wrong */ 270062306a36Sopenharmony_ci WARN_ON(1); 270162306a36Sopenharmony_ci log_error(ls, "%s %d %x %x %x %d %d %s", __func__, 270262306a36Sopenharmony_ci rv, lkb->lkb_id, dlm_iflags_val(lkb), args->flags, 270362306a36Sopenharmony_ci lkb->lkb_status, lkb->lkb_wait_type, 270462306a36Sopenharmony_ci lkb->lkb_resource->res_name); 270562306a36Sopenharmony_ci break; 270662306a36Sopenharmony_ci default: 270762306a36Sopenharmony_ci log_debug(ls, "%s %d %x %x %x %d %d %s", __func__, 270862306a36Sopenharmony_ci rv, lkb->lkb_id, dlm_iflags_val(lkb), args->flags, 270962306a36Sopenharmony_ci lkb->lkb_status, lkb->lkb_wait_type, 271062306a36Sopenharmony_ci lkb->lkb_resource->res_name); 271162306a36Sopenharmony_ci break; 271262306a36Sopenharmony_ci } 271362306a36Sopenharmony_ci 271462306a36Sopenharmony_ci return rv; 271562306a36Sopenharmony_ci} 271662306a36Sopenharmony_ci 271762306a36Sopenharmony_ci/* when dlm_unlock() sees -EBUSY with CANCEL/FORCEUNLOCK it returns 0 271862306a36Sopenharmony_ci for success */ 271962306a36Sopenharmony_ci 272062306a36Sopenharmony_ci/* note: it's valid for lkb_nodeid/res_nodeid to be -1 when we get here 272162306a36Sopenharmony_ci because there may be a lookup in progress and it's valid to do 272262306a36Sopenharmony_ci cancel/unlockf on it */ 272362306a36Sopenharmony_ci 272462306a36Sopenharmony_cistatic int validate_unlock_args(struct dlm_lkb *lkb, struct dlm_args *args) 272562306a36Sopenharmony_ci{ 272662306a36Sopenharmony_ci struct dlm_ls *ls = lkb->lkb_resource->res_ls; 272762306a36Sopenharmony_ci int rv = -EBUSY; 272862306a36Sopenharmony_ci 272962306a36Sopenharmony_ci /* normal unlock not allowed if there's any op in progress */ 273062306a36Sopenharmony_ci if (!(args->flags & (DLM_LKF_CANCEL | DLM_LKF_FORCEUNLOCK)) && 273162306a36Sopenharmony_ci (lkb->lkb_wait_type || atomic_read(&lkb->lkb_wait_count))) 273262306a36Sopenharmony_ci goto out; 273362306a36Sopenharmony_ci 273462306a36Sopenharmony_ci /* an lkb may be waiting for an rsb lookup to complete where the 273562306a36Sopenharmony_ci lookup was initiated by another lock */ 273662306a36Sopenharmony_ci 273762306a36Sopenharmony_ci if (!list_empty(&lkb->lkb_rsb_lookup)) { 273862306a36Sopenharmony_ci if (args->flags & (DLM_LKF_CANCEL | DLM_LKF_FORCEUNLOCK)) { 273962306a36Sopenharmony_ci log_debug(ls, "unlock on rsb_lookup %x", lkb->lkb_id); 274062306a36Sopenharmony_ci list_del_init(&lkb->lkb_rsb_lookup); 274162306a36Sopenharmony_ci queue_cast(lkb->lkb_resource, lkb, 274262306a36Sopenharmony_ci args->flags & DLM_LKF_CANCEL ? 274362306a36Sopenharmony_ci -DLM_ECANCEL : -DLM_EUNLOCK); 274462306a36Sopenharmony_ci unhold_lkb(lkb); /* undoes create_lkb() */ 274562306a36Sopenharmony_ci } 274662306a36Sopenharmony_ci /* caller changes -EBUSY to 0 for CANCEL and FORCEUNLOCK */ 274762306a36Sopenharmony_ci goto out; 274862306a36Sopenharmony_ci } 274962306a36Sopenharmony_ci 275062306a36Sopenharmony_ci rv = -EINVAL; 275162306a36Sopenharmony_ci if (test_bit(DLM_IFL_MSTCPY_BIT, &lkb->lkb_iflags)) { 275262306a36Sopenharmony_ci log_error(ls, "unlock on MSTCPY %x", lkb->lkb_id); 275362306a36Sopenharmony_ci dlm_print_lkb(lkb); 275462306a36Sopenharmony_ci goto out; 275562306a36Sopenharmony_ci } 275662306a36Sopenharmony_ci 275762306a36Sopenharmony_ci /* an lkb may still exist even though the lock is EOL'ed due to a 275862306a36Sopenharmony_ci * cancel, unlock or failed noqueue request; an app can't use these 275962306a36Sopenharmony_ci * locks; return same error as if the lkid had not been found at all 276062306a36Sopenharmony_ci */ 276162306a36Sopenharmony_ci 276262306a36Sopenharmony_ci if (test_bit(DLM_IFL_ENDOFLIFE_BIT, &lkb->lkb_iflags)) { 276362306a36Sopenharmony_ci log_debug(ls, "unlock on ENDOFLIFE %x", lkb->lkb_id); 276462306a36Sopenharmony_ci rv = -ENOENT; 276562306a36Sopenharmony_ci goto out; 276662306a36Sopenharmony_ci } 276762306a36Sopenharmony_ci 276862306a36Sopenharmony_ci /* cancel not allowed with another cancel/unlock in progress */ 276962306a36Sopenharmony_ci 277062306a36Sopenharmony_ci if (args->flags & DLM_LKF_CANCEL) { 277162306a36Sopenharmony_ci if (lkb->lkb_exflags & DLM_LKF_CANCEL) 277262306a36Sopenharmony_ci goto out; 277362306a36Sopenharmony_ci 277462306a36Sopenharmony_ci if (is_overlap(lkb)) 277562306a36Sopenharmony_ci goto out; 277662306a36Sopenharmony_ci 277762306a36Sopenharmony_ci if (test_bit(DLM_IFL_RESEND_BIT, &lkb->lkb_iflags)) { 277862306a36Sopenharmony_ci set_bit(DLM_IFL_OVERLAP_CANCEL_BIT, &lkb->lkb_iflags); 277962306a36Sopenharmony_ci rv = -EBUSY; 278062306a36Sopenharmony_ci goto out; 278162306a36Sopenharmony_ci } 278262306a36Sopenharmony_ci 278362306a36Sopenharmony_ci /* there's nothing to cancel */ 278462306a36Sopenharmony_ci if (lkb->lkb_status == DLM_LKSTS_GRANTED && 278562306a36Sopenharmony_ci !lkb->lkb_wait_type) { 278662306a36Sopenharmony_ci rv = -EBUSY; 278762306a36Sopenharmony_ci goto out; 278862306a36Sopenharmony_ci } 278962306a36Sopenharmony_ci 279062306a36Sopenharmony_ci switch (lkb->lkb_wait_type) { 279162306a36Sopenharmony_ci case DLM_MSG_LOOKUP: 279262306a36Sopenharmony_ci case DLM_MSG_REQUEST: 279362306a36Sopenharmony_ci set_bit(DLM_IFL_OVERLAP_CANCEL_BIT, &lkb->lkb_iflags); 279462306a36Sopenharmony_ci rv = -EBUSY; 279562306a36Sopenharmony_ci goto out; 279662306a36Sopenharmony_ci case DLM_MSG_UNLOCK: 279762306a36Sopenharmony_ci case DLM_MSG_CANCEL: 279862306a36Sopenharmony_ci goto out; 279962306a36Sopenharmony_ci } 280062306a36Sopenharmony_ci /* add_to_waiters() will set OVERLAP_CANCEL */ 280162306a36Sopenharmony_ci goto out_ok; 280262306a36Sopenharmony_ci } 280362306a36Sopenharmony_ci 280462306a36Sopenharmony_ci /* do we need to allow a force-unlock if there's a normal unlock 280562306a36Sopenharmony_ci already in progress? in what conditions could the normal unlock 280662306a36Sopenharmony_ci fail such that we'd want to send a force-unlock to be sure? */ 280762306a36Sopenharmony_ci 280862306a36Sopenharmony_ci if (args->flags & DLM_LKF_FORCEUNLOCK) { 280962306a36Sopenharmony_ci if (lkb->lkb_exflags & DLM_LKF_FORCEUNLOCK) 281062306a36Sopenharmony_ci goto out; 281162306a36Sopenharmony_ci 281262306a36Sopenharmony_ci if (is_overlap_unlock(lkb)) 281362306a36Sopenharmony_ci goto out; 281462306a36Sopenharmony_ci 281562306a36Sopenharmony_ci if (test_bit(DLM_IFL_RESEND_BIT, &lkb->lkb_iflags)) { 281662306a36Sopenharmony_ci set_bit(DLM_IFL_OVERLAP_UNLOCK_BIT, &lkb->lkb_iflags); 281762306a36Sopenharmony_ci rv = -EBUSY; 281862306a36Sopenharmony_ci goto out; 281962306a36Sopenharmony_ci } 282062306a36Sopenharmony_ci 282162306a36Sopenharmony_ci switch (lkb->lkb_wait_type) { 282262306a36Sopenharmony_ci case DLM_MSG_LOOKUP: 282362306a36Sopenharmony_ci case DLM_MSG_REQUEST: 282462306a36Sopenharmony_ci set_bit(DLM_IFL_OVERLAP_UNLOCK_BIT, &lkb->lkb_iflags); 282562306a36Sopenharmony_ci rv = -EBUSY; 282662306a36Sopenharmony_ci goto out; 282762306a36Sopenharmony_ci case DLM_MSG_UNLOCK: 282862306a36Sopenharmony_ci goto out; 282962306a36Sopenharmony_ci } 283062306a36Sopenharmony_ci /* add_to_waiters() will set OVERLAP_UNLOCK */ 283162306a36Sopenharmony_ci } 283262306a36Sopenharmony_ci 283362306a36Sopenharmony_ci out_ok: 283462306a36Sopenharmony_ci /* an overlapping op shouldn't blow away exflags from other op */ 283562306a36Sopenharmony_ci lkb->lkb_exflags |= args->flags; 283662306a36Sopenharmony_ci dlm_set_sbflags_val(lkb, 0); 283762306a36Sopenharmony_ci lkb->lkb_astparam = args->astparam; 283862306a36Sopenharmony_ci rv = 0; 283962306a36Sopenharmony_ci out: 284062306a36Sopenharmony_ci switch (rv) { 284162306a36Sopenharmony_ci case 0: 284262306a36Sopenharmony_ci break; 284362306a36Sopenharmony_ci case -EINVAL: 284462306a36Sopenharmony_ci /* annoy the user because dlm usage is wrong */ 284562306a36Sopenharmony_ci WARN_ON(1); 284662306a36Sopenharmony_ci log_error(ls, "%s %d %x %x %x %x %d %s", __func__, rv, 284762306a36Sopenharmony_ci lkb->lkb_id, dlm_iflags_val(lkb), lkb->lkb_exflags, 284862306a36Sopenharmony_ci args->flags, lkb->lkb_wait_type, 284962306a36Sopenharmony_ci lkb->lkb_resource->res_name); 285062306a36Sopenharmony_ci break; 285162306a36Sopenharmony_ci default: 285262306a36Sopenharmony_ci log_debug(ls, "%s %d %x %x %x %x %d %s", __func__, rv, 285362306a36Sopenharmony_ci lkb->lkb_id, dlm_iflags_val(lkb), lkb->lkb_exflags, 285462306a36Sopenharmony_ci args->flags, lkb->lkb_wait_type, 285562306a36Sopenharmony_ci lkb->lkb_resource->res_name); 285662306a36Sopenharmony_ci break; 285762306a36Sopenharmony_ci } 285862306a36Sopenharmony_ci 285962306a36Sopenharmony_ci return rv; 286062306a36Sopenharmony_ci} 286162306a36Sopenharmony_ci 286262306a36Sopenharmony_ci/* 286362306a36Sopenharmony_ci * Four stage 4 varieties: 286462306a36Sopenharmony_ci * do_request(), do_convert(), do_unlock(), do_cancel() 286562306a36Sopenharmony_ci * These are called on the master node for the given lock and 286662306a36Sopenharmony_ci * from the central locking logic. 286762306a36Sopenharmony_ci */ 286862306a36Sopenharmony_ci 286962306a36Sopenharmony_cistatic int do_request(struct dlm_rsb *r, struct dlm_lkb *lkb) 287062306a36Sopenharmony_ci{ 287162306a36Sopenharmony_ci int error = 0; 287262306a36Sopenharmony_ci 287362306a36Sopenharmony_ci if (can_be_granted(r, lkb, 1, 0, NULL)) { 287462306a36Sopenharmony_ci grant_lock(r, lkb); 287562306a36Sopenharmony_ci queue_cast(r, lkb, 0); 287662306a36Sopenharmony_ci goto out; 287762306a36Sopenharmony_ci } 287862306a36Sopenharmony_ci 287962306a36Sopenharmony_ci if (can_be_queued(lkb)) { 288062306a36Sopenharmony_ci error = -EINPROGRESS; 288162306a36Sopenharmony_ci add_lkb(r, lkb, DLM_LKSTS_WAITING); 288262306a36Sopenharmony_ci goto out; 288362306a36Sopenharmony_ci } 288462306a36Sopenharmony_ci 288562306a36Sopenharmony_ci error = -EAGAIN; 288662306a36Sopenharmony_ci queue_cast(r, lkb, -EAGAIN); 288762306a36Sopenharmony_ci out: 288862306a36Sopenharmony_ci return error; 288962306a36Sopenharmony_ci} 289062306a36Sopenharmony_ci 289162306a36Sopenharmony_cistatic void do_request_effects(struct dlm_rsb *r, struct dlm_lkb *lkb, 289262306a36Sopenharmony_ci int error) 289362306a36Sopenharmony_ci{ 289462306a36Sopenharmony_ci switch (error) { 289562306a36Sopenharmony_ci case -EAGAIN: 289662306a36Sopenharmony_ci if (force_blocking_asts(lkb)) 289762306a36Sopenharmony_ci send_blocking_asts_all(r, lkb); 289862306a36Sopenharmony_ci break; 289962306a36Sopenharmony_ci case -EINPROGRESS: 290062306a36Sopenharmony_ci send_blocking_asts(r, lkb); 290162306a36Sopenharmony_ci break; 290262306a36Sopenharmony_ci } 290362306a36Sopenharmony_ci} 290462306a36Sopenharmony_ci 290562306a36Sopenharmony_cistatic int do_convert(struct dlm_rsb *r, struct dlm_lkb *lkb) 290662306a36Sopenharmony_ci{ 290762306a36Sopenharmony_ci int error = 0; 290862306a36Sopenharmony_ci int deadlk = 0; 290962306a36Sopenharmony_ci 291062306a36Sopenharmony_ci /* changing an existing lock may allow others to be granted */ 291162306a36Sopenharmony_ci 291262306a36Sopenharmony_ci if (can_be_granted(r, lkb, 1, 0, &deadlk)) { 291362306a36Sopenharmony_ci grant_lock(r, lkb); 291462306a36Sopenharmony_ci queue_cast(r, lkb, 0); 291562306a36Sopenharmony_ci goto out; 291662306a36Sopenharmony_ci } 291762306a36Sopenharmony_ci 291862306a36Sopenharmony_ci /* can_be_granted() detected that this lock would block in a conversion 291962306a36Sopenharmony_ci deadlock, so we leave it on the granted queue and return EDEADLK in 292062306a36Sopenharmony_ci the ast for the convert. */ 292162306a36Sopenharmony_ci 292262306a36Sopenharmony_ci if (deadlk && !(lkb->lkb_exflags & DLM_LKF_NODLCKWT)) { 292362306a36Sopenharmony_ci /* it's left on the granted queue */ 292462306a36Sopenharmony_ci revert_lock(r, lkb); 292562306a36Sopenharmony_ci queue_cast(r, lkb, -EDEADLK); 292662306a36Sopenharmony_ci error = -EDEADLK; 292762306a36Sopenharmony_ci goto out; 292862306a36Sopenharmony_ci } 292962306a36Sopenharmony_ci 293062306a36Sopenharmony_ci /* is_demoted() means the can_be_granted() above set the grmode 293162306a36Sopenharmony_ci to NL, and left us on the granted queue. This auto-demotion 293262306a36Sopenharmony_ci (due to CONVDEADLK) might mean other locks, and/or this lock, are 293362306a36Sopenharmony_ci now grantable. We have to try to grant other converting locks 293462306a36Sopenharmony_ci before we try again to grant this one. */ 293562306a36Sopenharmony_ci 293662306a36Sopenharmony_ci if (is_demoted(lkb)) { 293762306a36Sopenharmony_ci grant_pending_convert(r, DLM_LOCK_IV, NULL, NULL); 293862306a36Sopenharmony_ci if (_can_be_granted(r, lkb, 1, 0)) { 293962306a36Sopenharmony_ci grant_lock(r, lkb); 294062306a36Sopenharmony_ci queue_cast(r, lkb, 0); 294162306a36Sopenharmony_ci goto out; 294262306a36Sopenharmony_ci } 294362306a36Sopenharmony_ci /* else fall through and move to convert queue */ 294462306a36Sopenharmony_ci } 294562306a36Sopenharmony_ci 294662306a36Sopenharmony_ci if (can_be_queued(lkb)) { 294762306a36Sopenharmony_ci error = -EINPROGRESS; 294862306a36Sopenharmony_ci del_lkb(r, lkb); 294962306a36Sopenharmony_ci add_lkb(r, lkb, DLM_LKSTS_CONVERT); 295062306a36Sopenharmony_ci goto out; 295162306a36Sopenharmony_ci } 295262306a36Sopenharmony_ci 295362306a36Sopenharmony_ci error = -EAGAIN; 295462306a36Sopenharmony_ci queue_cast(r, lkb, -EAGAIN); 295562306a36Sopenharmony_ci out: 295662306a36Sopenharmony_ci return error; 295762306a36Sopenharmony_ci} 295862306a36Sopenharmony_ci 295962306a36Sopenharmony_cistatic void do_convert_effects(struct dlm_rsb *r, struct dlm_lkb *lkb, 296062306a36Sopenharmony_ci int error) 296162306a36Sopenharmony_ci{ 296262306a36Sopenharmony_ci switch (error) { 296362306a36Sopenharmony_ci case 0: 296462306a36Sopenharmony_ci grant_pending_locks(r, NULL); 296562306a36Sopenharmony_ci /* grant_pending_locks also sends basts */ 296662306a36Sopenharmony_ci break; 296762306a36Sopenharmony_ci case -EAGAIN: 296862306a36Sopenharmony_ci if (force_blocking_asts(lkb)) 296962306a36Sopenharmony_ci send_blocking_asts_all(r, lkb); 297062306a36Sopenharmony_ci break; 297162306a36Sopenharmony_ci case -EINPROGRESS: 297262306a36Sopenharmony_ci send_blocking_asts(r, lkb); 297362306a36Sopenharmony_ci break; 297462306a36Sopenharmony_ci } 297562306a36Sopenharmony_ci} 297662306a36Sopenharmony_ci 297762306a36Sopenharmony_cistatic int do_unlock(struct dlm_rsb *r, struct dlm_lkb *lkb) 297862306a36Sopenharmony_ci{ 297962306a36Sopenharmony_ci remove_lock(r, lkb); 298062306a36Sopenharmony_ci queue_cast(r, lkb, -DLM_EUNLOCK); 298162306a36Sopenharmony_ci return -DLM_EUNLOCK; 298262306a36Sopenharmony_ci} 298362306a36Sopenharmony_ci 298462306a36Sopenharmony_cistatic void do_unlock_effects(struct dlm_rsb *r, struct dlm_lkb *lkb, 298562306a36Sopenharmony_ci int error) 298662306a36Sopenharmony_ci{ 298762306a36Sopenharmony_ci grant_pending_locks(r, NULL); 298862306a36Sopenharmony_ci} 298962306a36Sopenharmony_ci 299062306a36Sopenharmony_ci/* returns: 0 did nothing, -DLM_ECANCEL canceled lock */ 299162306a36Sopenharmony_ci 299262306a36Sopenharmony_cistatic int do_cancel(struct dlm_rsb *r, struct dlm_lkb *lkb) 299362306a36Sopenharmony_ci{ 299462306a36Sopenharmony_ci int error; 299562306a36Sopenharmony_ci 299662306a36Sopenharmony_ci error = revert_lock(r, lkb); 299762306a36Sopenharmony_ci if (error) { 299862306a36Sopenharmony_ci queue_cast(r, lkb, -DLM_ECANCEL); 299962306a36Sopenharmony_ci return -DLM_ECANCEL; 300062306a36Sopenharmony_ci } 300162306a36Sopenharmony_ci return 0; 300262306a36Sopenharmony_ci} 300362306a36Sopenharmony_ci 300462306a36Sopenharmony_cistatic void do_cancel_effects(struct dlm_rsb *r, struct dlm_lkb *lkb, 300562306a36Sopenharmony_ci int error) 300662306a36Sopenharmony_ci{ 300762306a36Sopenharmony_ci if (error) 300862306a36Sopenharmony_ci grant_pending_locks(r, NULL); 300962306a36Sopenharmony_ci} 301062306a36Sopenharmony_ci 301162306a36Sopenharmony_ci/* 301262306a36Sopenharmony_ci * Four stage 3 varieties: 301362306a36Sopenharmony_ci * _request_lock(), _convert_lock(), _unlock_lock(), _cancel_lock() 301462306a36Sopenharmony_ci */ 301562306a36Sopenharmony_ci 301662306a36Sopenharmony_ci/* add a new lkb to a possibly new rsb, called by requesting process */ 301762306a36Sopenharmony_ci 301862306a36Sopenharmony_cistatic int _request_lock(struct dlm_rsb *r, struct dlm_lkb *lkb) 301962306a36Sopenharmony_ci{ 302062306a36Sopenharmony_ci int error; 302162306a36Sopenharmony_ci 302262306a36Sopenharmony_ci /* set_master: sets lkb nodeid from r */ 302362306a36Sopenharmony_ci 302462306a36Sopenharmony_ci error = set_master(r, lkb); 302562306a36Sopenharmony_ci if (error < 0) 302662306a36Sopenharmony_ci goto out; 302762306a36Sopenharmony_ci if (error) { 302862306a36Sopenharmony_ci error = 0; 302962306a36Sopenharmony_ci goto out; 303062306a36Sopenharmony_ci } 303162306a36Sopenharmony_ci 303262306a36Sopenharmony_ci if (is_remote(r)) { 303362306a36Sopenharmony_ci /* receive_request() calls do_request() on remote node */ 303462306a36Sopenharmony_ci error = send_request(r, lkb); 303562306a36Sopenharmony_ci } else { 303662306a36Sopenharmony_ci error = do_request(r, lkb); 303762306a36Sopenharmony_ci /* for remote locks the request_reply is sent 303862306a36Sopenharmony_ci between do_request and do_request_effects */ 303962306a36Sopenharmony_ci do_request_effects(r, lkb, error); 304062306a36Sopenharmony_ci } 304162306a36Sopenharmony_ci out: 304262306a36Sopenharmony_ci return error; 304362306a36Sopenharmony_ci} 304462306a36Sopenharmony_ci 304562306a36Sopenharmony_ci/* change some property of an existing lkb, e.g. mode */ 304662306a36Sopenharmony_ci 304762306a36Sopenharmony_cistatic int _convert_lock(struct dlm_rsb *r, struct dlm_lkb *lkb) 304862306a36Sopenharmony_ci{ 304962306a36Sopenharmony_ci int error; 305062306a36Sopenharmony_ci 305162306a36Sopenharmony_ci if (is_remote(r)) { 305262306a36Sopenharmony_ci /* receive_convert() calls do_convert() on remote node */ 305362306a36Sopenharmony_ci error = send_convert(r, lkb); 305462306a36Sopenharmony_ci } else { 305562306a36Sopenharmony_ci error = do_convert(r, lkb); 305662306a36Sopenharmony_ci /* for remote locks the convert_reply is sent 305762306a36Sopenharmony_ci between do_convert and do_convert_effects */ 305862306a36Sopenharmony_ci do_convert_effects(r, lkb, error); 305962306a36Sopenharmony_ci } 306062306a36Sopenharmony_ci 306162306a36Sopenharmony_ci return error; 306262306a36Sopenharmony_ci} 306362306a36Sopenharmony_ci 306462306a36Sopenharmony_ci/* remove an existing lkb from the granted queue */ 306562306a36Sopenharmony_ci 306662306a36Sopenharmony_cistatic int _unlock_lock(struct dlm_rsb *r, struct dlm_lkb *lkb) 306762306a36Sopenharmony_ci{ 306862306a36Sopenharmony_ci int error; 306962306a36Sopenharmony_ci 307062306a36Sopenharmony_ci if (is_remote(r)) { 307162306a36Sopenharmony_ci /* receive_unlock() calls do_unlock() on remote node */ 307262306a36Sopenharmony_ci error = send_unlock(r, lkb); 307362306a36Sopenharmony_ci } else { 307462306a36Sopenharmony_ci error = do_unlock(r, lkb); 307562306a36Sopenharmony_ci /* for remote locks the unlock_reply is sent 307662306a36Sopenharmony_ci between do_unlock and do_unlock_effects */ 307762306a36Sopenharmony_ci do_unlock_effects(r, lkb, error); 307862306a36Sopenharmony_ci } 307962306a36Sopenharmony_ci 308062306a36Sopenharmony_ci return error; 308162306a36Sopenharmony_ci} 308262306a36Sopenharmony_ci 308362306a36Sopenharmony_ci/* remove an existing lkb from the convert or wait queue */ 308462306a36Sopenharmony_ci 308562306a36Sopenharmony_cistatic int _cancel_lock(struct dlm_rsb *r, struct dlm_lkb *lkb) 308662306a36Sopenharmony_ci{ 308762306a36Sopenharmony_ci int error; 308862306a36Sopenharmony_ci 308962306a36Sopenharmony_ci if (is_remote(r)) { 309062306a36Sopenharmony_ci /* receive_cancel() calls do_cancel() on remote node */ 309162306a36Sopenharmony_ci error = send_cancel(r, lkb); 309262306a36Sopenharmony_ci } else { 309362306a36Sopenharmony_ci error = do_cancel(r, lkb); 309462306a36Sopenharmony_ci /* for remote locks the cancel_reply is sent 309562306a36Sopenharmony_ci between do_cancel and do_cancel_effects */ 309662306a36Sopenharmony_ci do_cancel_effects(r, lkb, error); 309762306a36Sopenharmony_ci } 309862306a36Sopenharmony_ci 309962306a36Sopenharmony_ci return error; 310062306a36Sopenharmony_ci} 310162306a36Sopenharmony_ci 310262306a36Sopenharmony_ci/* 310362306a36Sopenharmony_ci * Four stage 2 varieties: 310462306a36Sopenharmony_ci * request_lock(), convert_lock(), unlock_lock(), cancel_lock() 310562306a36Sopenharmony_ci */ 310662306a36Sopenharmony_ci 310762306a36Sopenharmony_cistatic int request_lock(struct dlm_ls *ls, struct dlm_lkb *lkb, 310862306a36Sopenharmony_ci const void *name, int len, 310962306a36Sopenharmony_ci struct dlm_args *args) 311062306a36Sopenharmony_ci{ 311162306a36Sopenharmony_ci struct dlm_rsb *r; 311262306a36Sopenharmony_ci int error; 311362306a36Sopenharmony_ci 311462306a36Sopenharmony_ci error = validate_lock_args(ls, lkb, args); 311562306a36Sopenharmony_ci if (error) 311662306a36Sopenharmony_ci return error; 311762306a36Sopenharmony_ci 311862306a36Sopenharmony_ci error = find_rsb(ls, name, len, 0, R_REQUEST, &r); 311962306a36Sopenharmony_ci if (error) 312062306a36Sopenharmony_ci return error; 312162306a36Sopenharmony_ci 312262306a36Sopenharmony_ci lock_rsb(r); 312362306a36Sopenharmony_ci 312462306a36Sopenharmony_ci attach_lkb(r, lkb); 312562306a36Sopenharmony_ci lkb->lkb_lksb->sb_lkid = lkb->lkb_id; 312662306a36Sopenharmony_ci 312762306a36Sopenharmony_ci error = _request_lock(r, lkb); 312862306a36Sopenharmony_ci 312962306a36Sopenharmony_ci unlock_rsb(r); 313062306a36Sopenharmony_ci put_rsb(r); 313162306a36Sopenharmony_ci return error; 313262306a36Sopenharmony_ci} 313362306a36Sopenharmony_ci 313462306a36Sopenharmony_cistatic int convert_lock(struct dlm_ls *ls, struct dlm_lkb *lkb, 313562306a36Sopenharmony_ci struct dlm_args *args) 313662306a36Sopenharmony_ci{ 313762306a36Sopenharmony_ci struct dlm_rsb *r; 313862306a36Sopenharmony_ci int error; 313962306a36Sopenharmony_ci 314062306a36Sopenharmony_ci r = lkb->lkb_resource; 314162306a36Sopenharmony_ci 314262306a36Sopenharmony_ci hold_rsb(r); 314362306a36Sopenharmony_ci lock_rsb(r); 314462306a36Sopenharmony_ci 314562306a36Sopenharmony_ci error = validate_lock_args(ls, lkb, args); 314662306a36Sopenharmony_ci if (error) 314762306a36Sopenharmony_ci goto out; 314862306a36Sopenharmony_ci 314962306a36Sopenharmony_ci error = _convert_lock(r, lkb); 315062306a36Sopenharmony_ci out: 315162306a36Sopenharmony_ci unlock_rsb(r); 315262306a36Sopenharmony_ci put_rsb(r); 315362306a36Sopenharmony_ci return error; 315462306a36Sopenharmony_ci} 315562306a36Sopenharmony_ci 315662306a36Sopenharmony_cistatic int unlock_lock(struct dlm_ls *ls, struct dlm_lkb *lkb, 315762306a36Sopenharmony_ci struct dlm_args *args) 315862306a36Sopenharmony_ci{ 315962306a36Sopenharmony_ci struct dlm_rsb *r; 316062306a36Sopenharmony_ci int error; 316162306a36Sopenharmony_ci 316262306a36Sopenharmony_ci r = lkb->lkb_resource; 316362306a36Sopenharmony_ci 316462306a36Sopenharmony_ci hold_rsb(r); 316562306a36Sopenharmony_ci lock_rsb(r); 316662306a36Sopenharmony_ci 316762306a36Sopenharmony_ci error = validate_unlock_args(lkb, args); 316862306a36Sopenharmony_ci if (error) 316962306a36Sopenharmony_ci goto out; 317062306a36Sopenharmony_ci 317162306a36Sopenharmony_ci error = _unlock_lock(r, lkb); 317262306a36Sopenharmony_ci out: 317362306a36Sopenharmony_ci unlock_rsb(r); 317462306a36Sopenharmony_ci put_rsb(r); 317562306a36Sopenharmony_ci return error; 317662306a36Sopenharmony_ci} 317762306a36Sopenharmony_ci 317862306a36Sopenharmony_cistatic int cancel_lock(struct dlm_ls *ls, struct dlm_lkb *lkb, 317962306a36Sopenharmony_ci struct dlm_args *args) 318062306a36Sopenharmony_ci{ 318162306a36Sopenharmony_ci struct dlm_rsb *r; 318262306a36Sopenharmony_ci int error; 318362306a36Sopenharmony_ci 318462306a36Sopenharmony_ci r = lkb->lkb_resource; 318562306a36Sopenharmony_ci 318662306a36Sopenharmony_ci hold_rsb(r); 318762306a36Sopenharmony_ci lock_rsb(r); 318862306a36Sopenharmony_ci 318962306a36Sopenharmony_ci error = validate_unlock_args(lkb, args); 319062306a36Sopenharmony_ci if (error) 319162306a36Sopenharmony_ci goto out; 319262306a36Sopenharmony_ci 319362306a36Sopenharmony_ci error = _cancel_lock(r, lkb); 319462306a36Sopenharmony_ci out: 319562306a36Sopenharmony_ci unlock_rsb(r); 319662306a36Sopenharmony_ci put_rsb(r); 319762306a36Sopenharmony_ci return error; 319862306a36Sopenharmony_ci} 319962306a36Sopenharmony_ci 320062306a36Sopenharmony_ci/* 320162306a36Sopenharmony_ci * Two stage 1 varieties: dlm_lock() and dlm_unlock() 320262306a36Sopenharmony_ci */ 320362306a36Sopenharmony_ci 320462306a36Sopenharmony_ciint dlm_lock(dlm_lockspace_t *lockspace, 320562306a36Sopenharmony_ci int mode, 320662306a36Sopenharmony_ci struct dlm_lksb *lksb, 320762306a36Sopenharmony_ci uint32_t flags, 320862306a36Sopenharmony_ci const void *name, 320962306a36Sopenharmony_ci unsigned int namelen, 321062306a36Sopenharmony_ci uint32_t parent_lkid, 321162306a36Sopenharmony_ci void (*ast) (void *astarg), 321262306a36Sopenharmony_ci void *astarg, 321362306a36Sopenharmony_ci void (*bast) (void *astarg, int mode)) 321462306a36Sopenharmony_ci{ 321562306a36Sopenharmony_ci struct dlm_ls *ls; 321662306a36Sopenharmony_ci struct dlm_lkb *lkb; 321762306a36Sopenharmony_ci struct dlm_args args; 321862306a36Sopenharmony_ci int error, convert = flags & DLM_LKF_CONVERT; 321962306a36Sopenharmony_ci 322062306a36Sopenharmony_ci ls = dlm_find_lockspace_local(lockspace); 322162306a36Sopenharmony_ci if (!ls) 322262306a36Sopenharmony_ci return -EINVAL; 322362306a36Sopenharmony_ci 322462306a36Sopenharmony_ci dlm_lock_recovery(ls); 322562306a36Sopenharmony_ci 322662306a36Sopenharmony_ci if (convert) 322762306a36Sopenharmony_ci error = find_lkb(ls, lksb->sb_lkid, &lkb); 322862306a36Sopenharmony_ci else 322962306a36Sopenharmony_ci error = create_lkb(ls, &lkb); 323062306a36Sopenharmony_ci 323162306a36Sopenharmony_ci if (error) 323262306a36Sopenharmony_ci goto out; 323362306a36Sopenharmony_ci 323462306a36Sopenharmony_ci trace_dlm_lock_start(ls, lkb, name, namelen, mode, flags); 323562306a36Sopenharmony_ci 323662306a36Sopenharmony_ci error = set_lock_args(mode, lksb, flags, namelen, ast, astarg, bast, 323762306a36Sopenharmony_ci &args); 323862306a36Sopenharmony_ci if (error) 323962306a36Sopenharmony_ci goto out_put; 324062306a36Sopenharmony_ci 324162306a36Sopenharmony_ci if (convert) 324262306a36Sopenharmony_ci error = convert_lock(ls, lkb, &args); 324362306a36Sopenharmony_ci else 324462306a36Sopenharmony_ci error = request_lock(ls, lkb, name, namelen, &args); 324562306a36Sopenharmony_ci 324662306a36Sopenharmony_ci if (error == -EINPROGRESS) 324762306a36Sopenharmony_ci error = 0; 324862306a36Sopenharmony_ci out_put: 324962306a36Sopenharmony_ci trace_dlm_lock_end(ls, lkb, name, namelen, mode, flags, error, true); 325062306a36Sopenharmony_ci 325162306a36Sopenharmony_ci if (convert || error) 325262306a36Sopenharmony_ci __put_lkb(ls, lkb); 325362306a36Sopenharmony_ci if (error == -EAGAIN || error == -EDEADLK) 325462306a36Sopenharmony_ci error = 0; 325562306a36Sopenharmony_ci out: 325662306a36Sopenharmony_ci dlm_unlock_recovery(ls); 325762306a36Sopenharmony_ci dlm_put_lockspace(ls); 325862306a36Sopenharmony_ci return error; 325962306a36Sopenharmony_ci} 326062306a36Sopenharmony_ci 326162306a36Sopenharmony_ciint dlm_unlock(dlm_lockspace_t *lockspace, 326262306a36Sopenharmony_ci uint32_t lkid, 326362306a36Sopenharmony_ci uint32_t flags, 326462306a36Sopenharmony_ci struct dlm_lksb *lksb, 326562306a36Sopenharmony_ci void *astarg) 326662306a36Sopenharmony_ci{ 326762306a36Sopenharmony_ci struct dlm_ls *ls; 326862306a36Sopenharmony_ci struct dlm_lkb *lkb; 326962306a36Sopenharmony_ci struct dlm_args args; 327062306a36Sopenharmony_ci int error; 327162306a36Sopenharmony_ci 327262306a36Sopenharmony_ci ls = dlm_find_lockspace_local(lockspace); 327362306a36Sopenharmony_ci if (!ls) 327462306a36Sopenharmony_ci return -EINVAL; 327562306a36Sopenharmony_ci 327662306a36Sopenharmony_ci dlm_lock_recovery(ls); 327762306a36Sopenharmony_ci 327862306a36Sopenharmony_ci error = find_lkb(ls, lkid, &lkb); 327962306a36Sopenharmony_ci if (error) 328062306a36Sopenharmony_ci goto out; 328162306a36Sopenharmony_ci 328262306a36Sopenharmony_ci trace_dlm_unlock_start(ls, lkb, flags); 328362306a36Sopenharmony_ci 328462306a36Sopenharmony_ci error = set_unlock_args(flags, astarg, &args); 328562306a36Sopenharmony_ci if (error) 328662306a36Sopenharmony_ci goto out_put; 328762306a36Sopenharmony_ci 328862306a36Sopenharmony_ci if (flags & DLM_LKF_CANCEL) 328962306a36Sopenharmony_ci error = cancel_lock(ls, lkb, &args); 329062306a36Sopenharmony_ci else 329162306a36Sopenharmony_ci error = unlock_lock(ls, lkb, &args); 329262306a36Sopenharmony_ci 329362306a36Sopenharmony_ci if (error == -DLM_EUNLOCK || error == -DLM_ECANCEL) 329462306a36Sopenharmony_ci error = 0; 329562306a36Sopenharmony_ci if (error == -EBUSY && (flags & (DLM_LKF_CANCEL | DLM_LKF_FORCEUNLOCK))) 329662306a36Sopenharmony_ci error = 0; 329762306a36Sopenharmony_ci out_put: 329862306a36Sopenharmony_ci trace_dlm_unlock_end(ls, lkb, flags, error); 329962306a36Sopenharmony_ci 330062306a36Sopenharmony_ci dlm_put_lkb(lkb); 330162306a36Sopenharmony_ci out: 330262306a36Sopenharmony_ci dlm_unlock_recovery(ls); 330362306a36Sopenharmony_ci dlm_put_lockspace(ls); 330462306a36Sopenharmony_ci return error; 330562306a36Sopenharmony_ci} 330662306a36Sopenharmony_ci 330762306a36Sopenharmony_ci/* 330862306a36Sopenharmony_ci * send/receive routines for remote operations and replies 330962306a36Sopenharmony_ci * 331062306a36Sopenharmony_ci * send_args 331162306a36Sopenharmony_ci * send_common 331262306a36Sopenharmony_ci * send_request receive_request 331362306a36Sopenharmony_ci * send_convert receive_convert 331462306a36Sopenharmony_ci * send_unlock receive_unlock 331562306a36Sopenharmony_ci * send_cancel receive_cancel 331662306a36Sopenharmony_ci * send_grant receive_grant 331762306a36Sopenharmony_ci * send_bast receive_bast 331862306a36Sopenharmony_ci * send_lookup receive_lookup 331962306a36Sopenharmony_ci * send_remove receive_remove 332062306a36Sopenharmony_ci * 332162306a36Sopenharmony_ci * send_common_reply 332262306a36Sopenharmony_ci * receive_request_reply send_request_reply 332362306a36Sopenharmony_ci * receive_convert_reply send_convert_reply 332462306a36Sopenharmony_ci * receive_unlock_reply send_unlock_reply 332562306a36Sopenharmony_ci * receive_cancel_reply send_cancel_reply 332662306a36Sopenharmony_ci * receive_lookup_reply send_lookup_reply 332762306a36Sopenharmony_ci */ 332862306a36Sopenharmony_ci 332962306a36Sopenharmony_cistatic int _create_message(struct dlm_ls *ls, int mb_len, 333062306a36Sopenharmony_ci int to_nodeid, int mstype, 333162306a36Sopenharmony_ci struct dlm_message **ms_ret, 333262306a36Sopenharmony_ci struct dlm_mhandle **mh_ret, 333362306a36Sopenharmony_ci gfp_t allocation) 333462306a36Sopenharmony_ci{ 333562306a36Sopenharmony_ci struct dlm_message *ms; 333662306a36Sopenharmony_ci struct dlm_mhandle *mh; 333762306a36Sopenharmony_ci char *mb; 333862306a36Sopenharmony_ci 333962306a36Sopenharmony_ci /* get_buffer gives us a message handle (mh) that we need to 334062306a36Sopenharmony_ci pass into midcomms_commit and a message buffer (mb) that we 334162306a36Sopenharmony_ci write our data into */ 334262306a36Sopenharmony_ci 334362306a36Sopenharmony_ci mh = dlm_midcomms_get_mhandle(to_nodeid, mb_len, allocation, &mb); 334462306a36Sopenharmony_ci if (!mh) 334562306a36Sopenharmony_ci return -ENOBUFS; 334662306a36Sopenharmony_ci 334762306a36Sopenharmony_ci ms = (struct dlm_message *) mb; 334862306a36Sopenharmony_ci 334962306a36Sopenharmony_ci ms->m_header.h_version = cpu_to_le32(DLM_HEADER_MAJOR | DLM_HEADER_MINOR); 335062306a36Sopenharmony_ci ms->m_header.u.h_lockspace = cpu_to_le32(ls->ls_global_id); 335162306a36Sopenharmony_ci ms->m_header.h_nodeid = cpu_to_le32(dlm_our_nodeid()); 335262306a36Sopenharmony_ci ms->m_header.h_length = cpu_to_le16(mb_len); 335362306a36Sopenharmony_ci ms->m_header.h_cmd = DLM_MSG; 335462306a36Sopenharmony_ci 335562306a36Sopenharmony_ci ms->m_type = cpu_to_le32(mstype); 335662306a36Sopenharmony_ci 335762306a36Sopenharmony_ci *mh_ret = mh; 335862306a36Sopenharmony_ci *ms_ret = ms; 335962306a36Sopenharmony_ci return 0; 336062306a36Sopenharmony_ci} 336162306a36Sopenharmony_ci 336262306a36Sopenharmony_cistatic int create_message(struct dlm_rsb *r, struct dlm_lkb *lkb, 336362306a36Sopenharmony_ci int to_nodeid, int mstype, 336462306a36Sopenharmony_ci struct dlm_message **ms_ret, 336562306a36Sopenharmony_ci struct dlm_mhandle **mh_ret, 336662306a36Sopenharmony_ci gfp_t allocation) 336762306a36Sopenharmony_ci{ 336862306a36Sopenharmony_ci int mb_len = sizeof(struct dlm_message); 336962306a36Sopenharmony_ci 337062306a36Sopenharmony_ci switch (mstype) { 337162306a36Sopenharmony_ci case DLM_MSG_REQUEST: 337262306a36Sopenharmony_ci case DLM_MSG_LOOKUP: 337362306a36Sopenharmony_ci case DLM_MSG_REMOVE: 337462306a36Sopenharmony_ci mb_len += r->res_length; 337562306a36Sopenharmony_ci break; 337662306a36Sopenharmony_ci case DLM_MSG_CONVERT: 337762306a36Sopenharmony_ci case DLM_MSG_UNLOCK: 337862306a36Sopenharmony_ci case DLM_MSG_REQUEST_REPLY: 337962306a36Sopenharmony_ci case DLM_MSG_CONVERT_REPLY: 338062306a36Sopenharmony_ci case DLM_MSG_GRANT: 338162306a36Sopenharmony_ci if (lkb && lkb->lkb_lvbptr && (lkb->lkb_exflags & DLM_LKF_VALBLK)) 338262306a36Sopenharmony_ci mb_len += r->res_ls->ls_lvblen; 338362306a36Sopenharmony_ci break; 338462306a36Sopenharmony_ci } 338562306a36Sopenharmony_ci 338662306a36Sopenharmony_ci return _create_message(r->res_ls, mb_len, to_nodeid, mstype, 338762306a36Sopenharmony_ci ms_ret, mh_ret, allocation); 338862306a36Sopenharmony_ci} 338962306a36Sopenharmony_ci 339062306a36Sopenharmony_ci/* further lowcomms enhancements or alternate implementations may make 339162306a36Sopenharmony_ci the return value from this function useful at some point */ 339262306a36Sopenharmony_ci 339362306a36Sopenharmony_cistatic int send_message(struct dlm_mhandle *mh, struct dlm_message *ms, 339462306a36Sopenharmony_ci const void *name, int namelen) 339562306a36Sopenharmony_ci{ 339662306a36Sopenharmony_ci dlm_midcomms_commit_mhandle(mh, name, namelen); 339762306a36Sopenharmony_ci return 0; 339862306a36Sopenharmony_ci} 339962306a36Sopenharmony_ci 340062306a36Sopenharmony_cistatic void send_args(struct dlm_rsb *r, struct dlm_lkb *lkb, 340162306a36Sopenharmony_ci struct dlm_message *ms) 340262306a36Sopenharmony_ci{ 340362306a36Sopenharmony_ci ms->m_nodeid = cpu_to_le32(lkb->lkb_nodeid); 340462306a36Sopenharmony_ci ms->m_pid = cpu_to_le32(lkb->lkb_ownpid); 340562306a36Sopenharmony_ci ms->m_lkid = cpu_to_le32(lkb->lkb_id); 340662306a36Sopenharmony_ci ms->m_remid = cpu_to_le32(lkb->lkb_remid); 340762306a36Sopenharmony_ci ms->m_exflags = cpu_to_le32(lkb->lkb_exflags); 340862306a36Sopenharmony_ci ms->m_sbflags = cpu_to_le32(dlm_sbflags_val(lkb)); 340962306a36Sopenharmony_ci ms->m_flags = cpu_to_le32(dlm_dflags_val(lkb)); 341062306a36Sopenharmony_ci ms->m_lvbseq = cpu_to_le32(lkb->lkb_lvbseq); 341162306a36Sopenharmony_ci ms->m_status = cpu_to_le32(lkb->lkb_status); 341262306a36Sopenharmony_ci ms->m_grmode = cpu_to_le32(lkb->lkb_grmode); 341362306a36Sopenharmony_ci ms->m_rqmode = cpu_to_le32(lkb->lkb_rqmode); 341462306a36Sopenharmony_ci ms->m_hash = cpu_to_le32(r->res_hash); 341562306a36Sopenharmony_ci 341662306a36Sopenharmony_ci /* m_result and m_bastmode are set from function args, 341762306a36Sopenharmony_ci not from lkb fields */ 341862306a36Sopenharmony_ci 341962306a36Sopenharmony_ci if (lkb->lkb_bastfn) 342062306a36Sopenharmony_ci ms->m_asts |= cpu_to_le32(DLM_CB_BAST); 342162306a36Sopenharmony_ci if (lkb->lkb_astfn) 342262306a36Sopenharmony_ci ms->m_asts |= cpu_to_le32(DLM_CB_CAST); 342362306a36Sopenharmony_ci 342462306a36Sopenharmony_ci /* compare with switch in create_message; send_remove() doesn't 342562306a36Sopenharmony_ci use send_args() */ 342662306a36Sopenharmony_ci 342762306a36Sopenharmony_ci switch (ms->m_type) { 342862306a36Sopenharmony_ci case cpu_to_le32(DLM_MSG_REQUEST): 342962306a36Sopenharmony_ci case cpu_to_le32(DLM_MSG_LOOKUP): 343062306a36Sopenharmony_ci memcpy(ms->m_extra, r->res_name, r->res_length); 343162306a36Sopenharmony_ci break; 343262306a36Sopenharmony_ci case cpu_to_le32(DLM_MSG_CONVERT): 343362306a36Sopenharmony_ci case cpu_to_le32(DLM_MSG_UNLOCK): 343462306a36Sopenharmony_ci case cpu_to_le32(DLM_MSG_REQUEST_REPLY): 343562306a36Sopenharmony_ci case cpu_to_le32(DLM_MSG_CONVERT_REPLY): 343662306a36Sopenharmony_ci case cpu_to_le32(DLM_MSG_GRANT): 343762306a36Sopenharmony_ci if (!lkb->lkb_lvbptr || !(lkb->lkb_exflags & DLM_LKF_VALBLK)) 343862306a36Sopenharmony_ci break; 343962306a36Sopenharmony_ci memcpy(ms->m_extra, lkb->lkb_lvbptr, r->res_ls->ls_lvblen); 344062306a36Sopenharmony_ci break; 344162306a36Sopenharmony_ci } 344262306a36Sopenharmony_ci} 344362306a36Sopenharmony_ci 344462306a36Sopenharmony_cistatic int send_common(struct dlm_rsb *r, struct dlm_lkb *lkb, int mstype) 344562306a36Sopenharmony_ci{ 344662306a36Sopenharmony_ci struct dlm_message *ms; 344762306a36Sopenharmony_ci struct dlm_mhandle *mh; 344862306a36Sopenharmony_ci int to_nodeid, error; 344962306a36Sopenharmony_ci 345062306a36Sopenharmony_ci to_nodeid = r->res_nodeid; 345162306a36Sopenharmony_ci 345262306a36Sopenharmony_ci error = add_to_waiters(lkb, mstype, to_nodeid); 345362306a36Sopenharmony_ci if (error) 345462306a36Sopenharmony_ci return error; 345562306a36Sopenharmony_ci 345662306a36Sopenharmony_ci error = create_message(r, lkb, to_nodeid, mstype, &ms, &mh, GFP_NOFS); 345762306a36Sopenharmony_ci if (error) 345862306a36Sopenharmony_ci goto fail; 345962306a36Sopenharmony_ci 346062306a36Sopenharmony_ci send_args(r, lkb, ms); 346162306a36Sopenharmony_ci 346262306a36Sopenharmony_ci error = send_message(mh, ms, r->res_name, r->res_length); 346362306a36Sopenharmony_ci if (error) 346462306a36Sopenharmony_ci goto fail; 346562306a36Sopenharmony_ci return 0; 346662306a36Sopenharmony_ci 346762306a36Sopenharmony_ci fail: 346862306a36Sopenharmony_ci remove_from_waiters(lkb, msg_reply_type(mstype)); 346962306a36Sopenharmony_ci return error; 347062306a36Sopenharmony_ci} 347162306a36Sopenharmony_ci 347262306a36Sopenharmony_cistatic int send_request(struct dlm_rsb *r, struct dlm_lkb *lkb) 347362306a36Sopenharmony_ci{ 347462306a36Sopenharmony_ci return send_common(r, lkb, DLM_MSG_REQUEST); 347562306a36Sopenharmony_ci} 347662306a36Sopenharmony_ci 347762306a36Sopenharmony_cistatic int send_convert(struct dlm_rsb *r, struct dlm_lkb *lkb) 347862306a36Sopenharmony_ci{ 347962306a36Sopenharmony_ci int error; 348062306a36Sopenharmony_ci 348162306a36Sopenharmony_ci error = send_common(r, lkb, DLM_MSG_CONVERT); 348262306a36Sopenharmony_ci 348362306a36Sopenharmony_ci /* down conversions go without a reply from the master */ 348462306a36Sopenharmony_ci if (!error && down_conversion(lkb)) { 348562306a36Sopenharmony_ci remove_from_waiters(lkb, DLM_MSG_CONVERT_REPLY); 348662306a36Sopenharmony_ci r->res_ls->ls_local_ms.m_type = cpu_to_le32(DLM_MSG_CONVERT_REPLY); 348762306a36Sopenharmony_ci r->res_ls->ls_local_ms.m_result = 0; 348862306a36Sopenharmony_ci __receive_convert_reply(r, lkb, &r->res_ls->ls_local_ms, true); 348962306a36Sopenharmony_ci } 349062306a36Sopenharmony_ci 349162306a36Sopenharmony_ci return error; 349262306a36Sopenharmony_ci} 349362306a36Sopenharmony_ci 349462306a36Sopenharmony_ci/* FIXME: if this lkb is the only lock we hold on the rsb, then set 349562306a36Sopenharmony_ci MASTER_UNCERTAIN to force the next request on the rsb to confirm 349662306a36Sopenharmony_ci that the master is still correct. */ 349762306a36Sopenharmony_ci 349862306a36Sopenharmony_cistatic int send_unlock(struct dlm_rsb *r, struct dlm_lkb *lkb) 349962306a36Sopenharmony_ci{ 350062306a36Sopenharmony_ci return send_common(r, lkb, DLM_MSG_UNLOCK); 350162306a36Sopenharmony_ci} 350262306a36Sopenharmony_ci 350362306a36Sopenharmony_cistatic int send_cancel(struct dlm_rsb *r, struct dlm_lkb *lkb) 350462306a36Sopenharmony_ci{ 350562306a36Sopenharmony_ci return send_common(r, lkb, DLM_MSG_CANCEL); 350662306a36Sopenharmony_ci} 350762306a36Sopenharmony_ci 350862306a36Sopenharmony_cistatic int send_grant(struct dlm_rsb *r, struct dlm_lkb *lkb) 350962306a36Sopenharmony_ci{ 351062306a36Sopenharmony_ci struct dlm_message *ms; 351162306a36Sopenharmony_ci struct dlm_mhandle *mh; 351262306a36Sopenharmony_ci int to_nodeid, error; 351362306a36Sopenharmony_ci 351462306a36Sopenharmony_ci to_nodeid = lkb->lkb_nodeid; 351562306a36Sopenharmony_ci 351662306a36Sopenharmony_ci error = create_message(r, lkb, to_nodeid, DLM_MSG_GRANT, &ms, &mh, 351762306a36Sopenharmony_ci GFP_NOFS); 351862306a36Sopenharmony_ci if (error) 351962306a36Sopenharmony_ci goto out; 352062306a36Sopenharmony_ci 352162306a36Sopenharmony_ci send_args(r, lkb, ms); 352262306a36Sopenharmony_ci 352362306a36Sopenharmony_ci ms->m_result = 0; 352462306a36Sopenharmony_ci 352562306a36Sopenharmony_ci error = send_message(mh, ms, r->res_name, r->res_length); 352662306a36Sopenharmony_ci out: 352762306a36Sopenharmony_ci return error; 352862306a36Sopenharmony_ci} 352962306a36Sopenharmony_ci 353062306a36Sopenharmony_cistatic int send_bast(struct dlm_rsb *r, struct dlm_lkb *lkb, int mode) 353162306a36Sopenharmony_ci{ 353262306a36Sopenharmony_ci struct dlm_message *ms; 353362306a36Sopenharmony_ci struct dlm_mhandle *mh; 353462306a36Sopenharmony_ci int to_nodeid, error; 353562306a36Sopenharmony_ci 353662306a36Sopenharmony_ci to_nodeid = lkb->lkb_nodeid; 353762306a36Sopenharmony_ci 353862306a36Sopenharmony_ci error = create_message(r, NULL, to_nodeid, DLM_MSG_BAST, &ms, &mh, 353962306a36Sopenharmony_ci GFP_NOFS); 354062306a36Sopenharmony_ci if (error) 354162306a36Sopenharmony_ci goto out; 354262306a36Sopenharmony_ci 354362306a36Sopenharmony_ci send_args(r, lkb, ms); 354462306a36Sopenharmony_ci 354562306a36Sopenharmony_ci ms->m_bastmode = cpu_to_le32(mode); 354662306a36Sopenharmony_ci 354762306a36Sopenharmony_ci error = send_message(mh, ms, r->res_name, r->res_length); 354862306a36Sopenharmony_ci out: 354962306a36Sopenharmony_ci return error; 355062306a36Sopenharmony_ci} 355162306a36Sopenharmony_ci 355262306a36Sopenharmony_cistatic int send_lookup(struct dlm_rsb *r, struct dlm_lkb *lkb) 355362306a36Sopenharmony_ci{ 355462306a36Sopenharmony_ci struct dlm_message *ms; 355562306a36Sopenharmony_ci struct dlm_mhandle *mh; 355662306a36Sopenharmony_ci int to_nodeid, error; 355762306a36Sopenharmony_ci 355862306a36Sopenharmony_ci to_nodeid = dlm_dir_nodeid(r); 355962306a36Sopenharmony_ci 356062306a36Sopenharmony_ci error = add_to_waiters(lkb, DLM_MSG_LOOKUP, to_nodeid); 356162306a36Sopenharmony_ci if (error) 356262306a36Sopenharmony_ci return error; 356362306a36Sopenharmony_ci 356462306a36Sopenharmony_ci error = create_message(r, NULL, to_nodeid, DLM_MSG_LOOKUP, &ms, &mh, 356562306a36Sopenharmony_ci GFP_NOFS); 356662306a36Sopenharmony_ci if (error) 356762306a36Sopenharmony_ci goto fail; 356862306a36Sopenharmony_ci 356962306a36Sopenharmony_ci send_args(r, lkb, ms); 357062306a36Sopenharmony_ci 357162306a36Sopenharmony_ci error = send_message(mh, ms, r->res_name, r->res_length); 357262306a36Sopenharmony_ci if (error) 357362306a36Sopenharmony_ci goto fail; 357462306a36Sopenharmony_ci return 0; 357562306a36Sopenharmony_ci 357662306a36Sopenharmony_ci fail: 357762306a36Sopenharmony_ci remove_from_waiters(lkb, DLM_MSG_LOOKUP_REPLY); 357862306a36Sopenharmony_ci return error; 357962306a36Sopenharmony_ci} 358062306a36Sopenharmony_ci 358162306a36Sopenharmony_cistatic int send_remove(struct dlm_rsb *r) 358262306a36Sopenharmony_ci{ 358362306a36Sopenharmony_ci struct dlm_message *ms; 358462306a36Sopenharmony_ci struct dlm_mhandle *mh; 358562306a36Sopenharmony_ci int to_nodeid, error; 358662306a36Sopenharmony_ci 358762306a36Sopenharmony_ci to_nodeid = dlm_dir_nodeid(r); 358862306a36Sopenharmony_ci 358962306a36Sopenharmony_ci error = create_message(r, NULL, to_nodeid, DLM_MSG_REMOVE, &ms, &mh, 359062306a36Sopenharmony_ci GFP_ATOMIC); 359162306a36Sopenharmony_ci if (error) 359262306a36Sopenharmony_ci goto out; 359362306a36Sopenharmony_ci 359462306a36Sopenharmony_ci memcpy(ms->m_extra, r->res_name, r->res_length); 359562306a36Sopenharmony_ci ms->m_hash = cpu_to_le32(r->res_hash); 359662306a36Sopenharmony_ci 359762306a36Sopenharmony_ci error = send_message(mh, ms, r->res_name, r->res_length); 359862306a36Sopenharmony_ci out: 359962306a36Sopenharmony_ci return error; 360062306a36Sopenharmony_ci} 360162306a36Sopenharmony_ci 360262306a36Sopenharmony_cistatic int send_common_reply(struct dlm_rsb *r, struct dlm_lkb *lkb, 360362306a36Sopenharmony_ci int mstype, int rv) 360462306a36Sopenharmony_ci{ 360562306a36Sopenharmony_ci struct dlm_message *ms; 360662306a36Sopenharmony_ci struct dlm_mhandle *mh; 360762306a36Sopenharmony_ci int to_nodeid, error; 360862306a36Sopenharmony_ci 360962306a36Sopenharmony_ci to_nodeid = lkb->lkb_nodeid; 361062306a36Sopenharmony_ci 361162306a36Sopenharmony_ci error = create_message(r, lkb, to_nodeid, mstype, &ms, &mh, GFP_NOFS); 361262306a36Sopenharmony_ci if (error) 361362306a36Sopenharmony_ci goto out; 361462306a36Sopenharmony_ci 361562306a36Sopenharmony_ci send_args(r, lkb, ms); 361662306a36Sopenharmony_ci 361762306a36Sopenharmony_ci ms->m_result = cpu_to_le32(to_dlm_errno(rv)); 361862306a36Sopenharmony_ci 361962306a36Sopenharmony_ci error = send_message(mh, ms, r->res_name, r->res_length); 362062306a36Sopenharmony_ci out: 362162306a36Sopenharmony_ci return error; 362262306a36Sopenharmony_ci} 362362306a36Sopenharmony_ci 362462306a36Sopenharmony_cistatic int send_request_reply(struct dlm_rsb *r, struct dlm_lkb *lkb, int rv) 362562306a36Sopenharmony_ci{ 362662306a36Sopenharmony_ci return send_common_reply(r, lkb, DLM_MSG_REQUEST_REPLY, rv); 362762306a36Sopenharmony_ci} 362862306a36Sopenharmony_ci 362962306a36Sopenharmony_cistatic int send_convert_reply(struct dlm_rsb *r, struct dlm_lkb *lkb, int rv) 363062306a36Sopenharmony_ci{ 363162306a36Sopenharmony_ci return send_common_reply(r, lkb, DLM_MSG_CONVERT_REPLY, rv); 363262306a36Sopenharmony_ci} 363362306a36Sopenharmony_ci 363462306a36Sopenharmony_cistatic int send_unlock_reply(struct dlm_rsb *r, struct dlm_lkb *lkb, int rv) 363562306a36Sopenharmony_ci{ 363662306a36Sopenharmony_ci return send_common_reply(r, lkb, DLM_MSG_UNLOCK_REPLY, rv); 363762306a36Sopenharmony_ci} 363862306a36Sopenharmony_ci 363962306a36Sopenharmony_cistatic int send_cancel_reply(struct dlm_rsb *r, struct dlm_lkb *lkb, int rv) 364062306a36Sopenharmony_ci{ 364162306a36Sopenharmony_ci return send_common_reply(r, lkb, DLM_MSG_CANCEL_REPLY, rv); 364262306a36Sopenharmony_ci} 364362306a36Sopenharmony_ci 364462306a36Sopenharmony_cistatic int send_lookup_reply(struct dlm_ls *ls, 364562306a36Sopenharmony_ci const struct dlm_message *ms_in, int ret_nodeid, 364662306a36Sopenharmony_ci int rv) 364762306a36Sopenharmony_ci{ 364862306a36Sopenharmony_ci struct dlm_rsb *r = &ls->ls_local_rsb; 364962306a36Sopenharmony_ci struct dlm_message *ms; 365062306a36Sopenharmony_ci struct dlm_mhandle *mh; 365162306a36Sopenharmony_ci int error, nodeid = le32_to_cpu(ms_in->m_header.h_nodeid); 365262306a36Sopenharmony_ci 365362306a36Sopenharmony_ci error = create_message(r, NULL, nodeid, DLM_MSG_LOOKUP_REPLY, &ms, &mh, 365462306a36Sopenharmony_ci GFP_NOFS); 365562306a36Sopenharmony_ci if (error) 365662306a36Sopenharmony_ci goto out; 365762306a36Sopenharmony_ci 365862306a36Sopenharmony_ci ms->m_lkid = ms_in->m_lkid; 365962306a36Sopenharmony_ci ms->m_result = cpu_to_le32(to_dlm_errno(rv)); 366062306a36Sopenharmony_ci ms->m_nodeid = cpu_to_le32(ret_nodeid); 366162306a36Sopenharmony_ci 366262306a36Sopenharmony_ci error = send_message(mh, ms, ms_in->m_extra, receive_extralen(ms_in)); 366362306a36Sopenharmony_ci out: 366462306a36Sopenharmony_ci return error; 366562306a36Sopenharmony_ci} 366662306a36Sopenharmony_ci 366762306a36Sopenharmony_ci/* which args we save from a received message depends heavily on the type 366862306a36Sopenharmony_ci of message, unlike the send side where we can safely send everything about 366962306a36Sopenharmony_ci the lkb for any type of message */ 367062306a36Sopenharmony_ci 367162306a36Sopenharmony_cistatic void receive_flags(struct dlm_lkb *lkb, const struct dlm_message *ms) 367262306a36Sopenharmony_ci{ 367362306a36Sopenharmony_ci lkb->lkb_exflags = le32_to_cpu(ms->m_exflags); 367462306a36Sopenharmony_ci dlm_set_sbflags_val(lkb, le32_to_cpu(ms->m_sbflags)); 367562306a36Sopenharmony_ci dlm_set_dflags_val(lkb, le32_to_cpu(ms->m_flags)); 367662306a36Sopenharmony_ci} 367762306a36Sopenharmony_ci 367862306a36Sopenharmony_cistatic void receive_flags_reply(struct dlm_lkb *lkb, 367962306a36Sopenharmony_ci const struct dlm_message *ms, 368062306a36Sopenharmony_ci bool local) 368162306a36Sopenharmony_ci{ 368262306a36Sopenharmony_ci if (local) 368362306a36Sopenharmony_ci return; 368462306a36Sopenharmony_ci 368562306a36Sopenharmony_ci dlm_set_sbflags_val(lkb, le32_to_cpu(ms->m_sbflags)); 368662306a36Sopenharmony_ci dlm_set_dflags_val(lkb, le32_to_cpu(ms->m_flags)); 368762306a36Sopenharmony_ci} 368862306a36Sopenharmony_ci 368962306a36Sopenharmony_cistatic int receive_extralen(const struct dlm_message *ms) 369062306a36Sopenharmony_ci{ 369162306a36Sopenharmony_ci return (le16_to_cpu(ms->m_header.h_length) - 369262306a36Sopenharmony_ci sizeof(struct dlm_message)); 369362306a36Sopenharmony_ci} 369462306a36Sopenharmony_ci 369562306a36Sopenharmony_cistatic int receive_lvb(struct dlm_ls *ls, struct dlm_lkb *lkb, 369662306a36Sopenharmony_ci const struct dlm_message *ms) 369762306a36Sopenharmony_ci{ 369862306a36Sopenharmony_ci int len; 369962306a36Sopenharmony_ci 370062306a36Sopenharmony_ci if (lkb->lkb_exflags & DLM_LKF_VALBLK) { 370162306a36Sopenharmony_ci if (!lkb->lkb_lvbptr) 370262306a36Sopenharmony_ci lkb->lkb_lvbptr = dlm_allocate_lvb(ls); 370362306a36Sopenharmony_ci if (!lkb->lkb_lvbptr) 370462306a36Sopenharmony_ci return -ENOMEM; 370562306a36Sopenharmony_ci len = receive_extralen(ms); 370662306a36Sopenharmony_ci if (len > ls->ls_lvblen) 370762306a36Sopenharmony_ci len = ls->ls_lvblen; 370862306a36Sopenharmony_ci memcpy(lkb->lkb_lvbptr, ms->m_extra, len); 370962306a36Sopenharmony_ci } 371062306a36Sopenharmony_ci return 0; 371162306a36Sopenharmony_ci} 371262306a36Sopenharmony_ci 371362306a36Sopenharmony_cistatic void fake_bastfn(void *astparam, int mode) 371462306a36Sopenharmony_ci{ 371562306a36Sopenharmony_ci log_print("fake_bastfn should not be called"); 371662306a36Sopenharmony_ci} 371762306a36Sopenharmony_ci 371862306a36Sopenharmony_cistatic void fake_astfn(void *astparam) 371962306a36Sopenharmony_ci{ 372062306a36Sopenharmony_ci log_print("fake_astfn should not be called"); 372162306a36Sopenharmony_ci} 372262306a36Sopenharmony_ci 372362306a36Sopenharmony_cistatic int receive_request_args(struct dlm_ls *ls, struct dlm_lkb *lkb, 372462306a36Sopenharmony_ci const struct dlm_message *ms) 372562306a36Sopenharmony_ci{ 372662306a36Sopenharmony_ci lkb->lkb_nodeid = le32_to_cpu(ms->m_header.h_nodeid); 372762306a36Sopenharmony_ci lkb->lkb_ownpid = le32_to_cpu(ms->m_pid); 372862306a36Sopenharmony_ci lkb->lkb_remid = le32_to_cpu(ms->m_lkid); 372962306a36Sopenharmony_ci lkb->lkb_grmode = DLM_LOCK_IV; 373062306a36Sopenharmony_ci lkb->lkb_rqmode = le32_to_cpu(ms->m_rqmode); 373162306a36Sopenharmony_ci 373262306a36Sopenharmony_ci lkb->lkb_bastfn = (ms->m_asts & cpu_to_le32(DLM_CB_BAST)) ? &fake_bastfn : NULL; 373362306a36Sopenharmony_ci lkb->lkb_astfn = (ms->m_asts & cpu_to_le32(DLM_CB_CAST)) ? &fake_astfn : NULL; 373462306a36Sopenharmony_ci 373562306a36Sopenharmony_ci if (lkb->lkb_exflags & DLM_LKF_VALBLK) { 373662306a36Sopenharmony_ci /* lkb was just created so there won't be an lvb yet */ 373762306a36Sopenharmony_ci lkb->lkb_lvbptr = dlm_allocate_lvb(ls); 373862306a36Sopenharmony_ci if (!lkb->lkb_lvbptr) 373962306a36Sopenharmony_ci return -ENOMEM; 374062306a36Sopenharmony_ci } 374162306a36Sopenharmony_ci 374262306a36Sopenharmony_ci return 0; 374362306a36Sopenharmony_ci} 374462306a36Sopenharmony_ci 374562306a36Sopenharmony_cistatic int receive_convert_args(struct dlm_ls *ls, struct dlm_lkb *lkb, 374662306a36Sopenharmony_ci const struct dlm_message *ms) 374762306a36Sopenharmony_ci{ 374862306a36Sopenharmony_ci if (lkb->lkb_status != DLM_LKSTS_GRANTED) 374962306a36Sopenharmony_ci return -EBUSY; 375062306a36Sopenharmony_ci 375162306a36Sopenharmony_ci if (receive_lvb(ls, lkb, ms)) 375262306a36Sopenharmony_ci return -ENOMEM; 375362306a36Sopenharmony_ci 375462306a36Sopenharmony_ci lkb->lkb_rqmode = le32_to_cpu(ms->m_rqmode); 375562306a36Sopenharmony_ci lkb->lkb_lvbseq = le32_to_cpu(ms->m_lvbseq); 375662306a36Sopenharmony_ci 375762306a36Sopenharmony_ci return 0; 375862306a36Sopenharmony_ci} 375962306a36Sopenharmony_ci 376062306a36Sopenharmony_cistatic int receive_unlock_args(struct dlm_ls *ls, struct dlm_lkb *lkb, 376162306a36Sopenharmony_ci const struct dlm_message *ms) 376262306a36Sopenharmony_ci{ 376362306a36Sopenharmony_ci if (receive_lvb(ls, lkb, ms)) 376462306a36Sopenharmony_ci return -ENOMEM; 376562306a36Sopenharmony_ci return 0; 376662306a36Sopenharmony_ci} 376762306a36Sopenharmony_ci 376862306a36Sopenharmony_ci/* We fill in the local-lkb fields with the info that send_xxxx_reply() 376962306a36Sopenharmony_ci uses to send a reply and that the remote end uses to process the reply. */ 377062306a36Sopenharmony_ci 377162306a36Sopenharmony_cistatic void setup_local_lkb(struct dlm_ls *ls, const struct dlm_message *ms) 377262306a36Sopenharmony_ci{ 377362306a36Sopenharmony_ci struct dlm_lkb *lkb = &ls->ls_local_lkb; 377462306a36Sopenharmony_ci lkb->lkb_nodeid = le32_to_cpu(ms->m_header.h_nodeid); 377562306a36Sopenharmony_ci lkb->lkb_remid = le32_to_cpu(ms->m_lkid); 377662306a36Sopenharmony_ci} 377762306a36Sopenharmony_ci 377862306a36Sopenharmony_ci/* This is called after the rsb is locked so that we can safely inspect 377962306a36Sopenharmony_ci fields in the lkb. */ 378062306a36Sopenharmony_ci 378162306a36Sopenharmony_cistatic int validate_message(struct dlm_lkb *lkb, const struct dlm_message *ms) 378262306a36Sopenharmony_ci{ 378362306a36Sopenharmony_ci int from = le32_to_cpu(ms->m_header.h_nodeid); 378462306a36Sopenharmony_ci int error = 0; 378562306a36Sopenharmony_ci 378662306a36Sopenharmony_ci /* currently mixing of user/kernel locks are not supported */ 378762306a36Sopenharmony_ci if (ms->m_flags & cpu_to_le32(BIT(DLM_DFL_USER_BIT)) && 378862306a36Sopenharmony_ci !test_bit(DLM_DFL_USER_BIT, &lkb->lkb_dflags)) { 378962306a36Sopenharmony_ci log_error(lkb->lkb_resource->res_ls, 379062306a36Sopenharmony_ci "got user dlm message for a kernel lock"); 379162306a36Sopenharmony_ci error = -EINVAL; 379262306a36Sopenharmony_ci goto out; 379362306a36Sopenharmony_ci } 379462306a36Sopenharmony_ci 379562306a36Sopenharmony_ci switch (ms->m_type) { 379662306a36Sopenharmony_ci case cpu_to_le32(DLM_MSG_CONVERT): 379762306a36Sopenharmony_ci case cpu_to_le32(DLM_MSG_UNLOCK): 379862306a36Sopenharmony_ci case cpu_to_le32(DLM_MSG_CANCEL): 379962306a36Sopenharmony_ci if (!is_master_copy(lkb) || lkb->lkb_nodeid != from) 380062306a36Sopenharmony_ci error = -EINVAL; 380162306a36Sopenharmony_ci break; 380262306a36Sopenharmony_ci 380362306a36Sopenharmony_ci case cpu_to_le32(DLM_MSG_CONVERT_REPLY): 380462306a36Sopenharmony_ci case cpu_to_le32(DLM_MSG_UNLOCK_REPLY): 380562306a36Sopenharmony_ci case cpu_to_le32(DLM_MSG_CANCEL_REPLY): 380662306a36Sopenharmony_ci case cpu_to_le32(DLM_MSG_GRANT): 380762306a36Sopenharmony_ci case cpu_to_le32(DLM_MSG_BAST): 380862306a36Sopenharmony_ci if (!is_process_copy(lkb) || lkb->lkb_nodeid != from) 380962306a36Sopenharmony_ci error = -EINVAL; 381062306a36Sopenharmony_ci break; 381162306a36Sopenharmony_ci 381262306a36Sopenharmony_ci case cpu_to_le32(DLM_MSG_REQUEST_REPLY): 381362306a36Sopenharmony_ci if (!is_process_copy(lkb)) 381462306a36Sopenharmony_ci error = -EINVAL; 381562306a36Sopenharmony_ci else if (lkb->lkb_nodeid != -1 && lkb->lkb_nodeid != from) 381662306a36Sopenharmony_ci error = -EINVAL; 381762306a36Sopenharmony_ci break; 381862306a36Sopenharmony_ci 381962306a36Sopenharmony_ci default: 382062306a36Sopenharmony_ci error = -EINVAL; 382162306a36Sopenharmony_ci } 382262306a36Sopenharmony_ci 382362306a36Sopenharmony_ciout: 382462306a36Sopenharmony_ci if (error) 382562306a36Sopenharmony_ci log_error(lkb->lkb_resource->res_ls, 382662306a36Sopenharmony_ci "ignore invalid message %d from %d %x %x %x %d", 382762306a36Sopenharmony_ci le32_to_cpu(ms->m_type), from, lkb->lkb_id, 382862306a36Sopenharmony_ci lkb->lkb_remid, dlm_iflags_val(lkb), 382962306a36Sopenharmony_ci lkb->lkb_nodeid); 383062306a36Sopenharmony_ci return error; 383162306a36Sopenharmony_ci} 383262306a36Sopenharmony_ci 383362306a36Sopenharmony_cistatic int receive_request(struct dlm_ls *ls, const struct dlm_message *ms) 383462306a36Sopenharmony_ci{ 383562306a36Sopenharmony_ci struct dlm_lkb *lkb; 383662306a36Sopenharmony_ci struct dlm_rsb *r; 383762306a36Sopenharmony_ci int from_nodeid; 383862306a36Sopenharmony_ci int error, namelen = 0; 383962306a36Sopenharmony_ci 384062306a36Sopenharmony_ci from_nodeid = le32_to_cpu(ms->m_header.h_nodeid); 384162306a36Sopenharmony_ci 384262306a36Sopenharmony_ci error = create_lkb(ls, &lkb); 384362306a36Sopenharmony_ci if (error) 384462306a36Sopenharmony_ci goto fail; 384562306a36Sopenharmony_ci 384662306a36Sopenharmony_ci receive_flags(lkb, ms); 384762306a36Sopenharmony_ci set_bit(DLM_IFL_MSTCPY_BIT, &lkb->lkb_iflags); 384862306a36Sopenharmony_ci error = receive_request_args(ls, lkb, ms); 384962306a36Sopenharmony_ci if (error) { 385062306a36Sopenharmony_ci __put_lkb(ls, lkb); 385162306a36Sopenharmony_ci goto fail; 385262306a36Sopenharmony_ci } 385362306a36Sopenharmony_ci 385462306a36Sopenharmony_ci /* The dir node is the authority on whether we are the master 385562306a36Sopenharmony_ci for this rsb or not, so if the master sends us a request, we should 385662306a36Sopenharmony_ci recreate the rsb if we've destroyed it. This race happens when we 385762306a36Sopenharmony_ci send a remove message to the dir node at the same time that the dir 385862306a36Sopenharmony_ci node sends us a request for the rsb. */ 385962306a36Sopenharmony_ci 386062306a36Sopenharmony_ci namelen = receive_extralen(ms); 386162306a36Sopenharmony_ci 386262306a36Sopenharmony_ci error = find_rsb(ls, ms->m_extra, namelen, from_nodeid, 386362306a36Sopenharmony_ci R_RECEIVE_REQUEST, &r); 386462306a36Sopenharmony_ci if (error) { 386562306a36Sopenharmony_ci __put_lkb(ls, lkb); 386662306a36Sopenharmony_ci goto fail; 386762306a36Sopenharmony_ci } 386862306a36Sopenharmony_ci 386962306a36Sopenharmony_ci lock_rsb(r); 387062306a36Sopenharmony_ci 387162306a36Sopenharmony_ci if (r->res_master_nodeid != dlm_our_nodeid()) { 387262306a36Sopenharmony_ci error = validate_master_nodeid(ls, r, from_nodeid); 387362306a36Sopenharmony_ci if (error) { 387462306a36Sopenharmony_ci unlock_rsb(r); 387562306a36Sopenharmony_ci put_rsb(r); 387662306a36Sopenharmony_ci __put_lkb(ls, lkb); 387762306a36Sopenharmony_ci goto fail; 387862306a36Sopenharmony_ci } 387962306a36Sopenharmony_ci } 388062306a36Sopenharmony_ci 388162306a36Sopenharmony_ci attach_lkb(r, lkb); 388262306a36Sopenharmony_ci error = do_request(r, lkb); 388362306a36Sopenharmony_ci send_request_reply(r, lkb, error); 388462306a36Sopenharmony_ci do_request_effects(r, lkb, error); 388562306a36Sopenharmony_ci 388662306a36Sopenharmony_ci unlock_rsb(r); 388762306a36Sopenharmony_ci put_rsb(r); 388862306a36Sopenharmony_ci 388962306a36Sopenharmony_ci if (error == -EINPROGRESS) 389062306a36Sopenharmony_ci error = 0; 389162306a36Sopenharmony_ci if (error) 389262306a36Sopenharmony_ci dlm_put_lkb(lkb); 389362306a36Sopenharmony_ci return 0; 389462306a36Sopenharmony_ci 389562306a36Sopenharmony_ci fail: 389662306a36Sopenharmony_ci /* TODO: instead of returning ENOTBLK, add the lkb to res_lookup 389762306a36Sopenharmony_ci and do this receive_request again from process_lookup_list once 389862306a36Sopenharmony_ci we get the lookup reply. This would avoid a many repeated 389962306a36Sopenharmony_ci ENOTBLK request failures when the lookup reply designating us 390062306a36Sopenharmony_ci as master is delayed. */ 390162306a36Sopenharmony_ci 390262306a36Sopenharmony_ci if (error != -ENOTBLK) { 390362306a36Sopenharmony_ci log_limit(ls, "receive_request %x from %d %d", 390462306a36Sopenharmony_ci le32_to_cpu(ms->m_lkid), from_nodeid, error); 390562306a36Sopenharmony_ci } 390662306a36Sopenharmony_ci 390762306a36Sopenharmony_ci setup_local_lkb(ls, ms); 390862306a36Sopenharmony_ci send_request_reply(&ls->ls_local_rsb, &ls->ls_local_lkb, error); 390962306a36Sopenharmony_ci return error; 391062306a36Sopenharmony_ci} 391162306a36Sopenharmony_ci 391262306a36Sopenharmony_cistatic int receive_convert(struct dlm_ls *ls, const struct dlm_message *ms) 391362306a36Sopenharmony_ci{ 391462306a36Sopenharmony_ci struct dlm_lkb *lkb; 391562306a36Sopenharmony_ci struct dlm_rsb *r; 391662306a36Sopenharmony_ci int error, reply = 1; 391762306a36Sopenharmony_ci 391862306a36Sopenharmony_ci error = find_lkb(ls, le32_to_cpu(ms->m_remid), &lkb); 391962306a36Sopenharmony_ci if (error) 392062306a36Sopenharmony_ci goto fail; 392162306a36Sopenharmony_ci 392262306a36Sopenharmony_ci if (lkb->lkb_remid != le32_to_cpu(ms->m_lkid)) { 392362306a36Sopenharmony_ci log_error(ls, "receive_convert %x remid %x recover_seq %llu " 392462306a36Sopenharmony_ci "remote %d %x", lkb->lkb_id, lkb->lkb_remid, 392562306a36Sopenharmony_ci (unsigned long long)lkb->lkb_recover_seq, 392662306a36Sopenharmony_ci le32_to_cpu(ms->m_header.h_nodeid), 392762306a36Sopenharmony_ci le32_to_cpu(ms->m_lkid)); 392862306a36Sopenharmony_ci error = -ENOENT; 392962306a36Sopenharmony_ci dlm_put_lkb(lkb); 393062306a36Sopenharmony_ci goto fail; 393162306a36Sopenharmony_ci } 393262306a36Sopenharmony_ci 393362306a36Sopenharmony_ci r = lkb->lkb_resource; 393462306a36Sopenharmony_ci 393562306a36Sopenharmony_ci hold_rsb(r); 393662306a36Sopenharmony_ci lock_rsb(r); 393762306a36Sopenharmony_ci 393862306a36Sopenharmony_ci error = validate_message(lkb, ms); 393962306a36Sopenharmony_ci if (error) 394062306a36Sopenharmony_ci goto out; 394162306a36Sopenharmony_ci 394262306a36Sopenharmony_ci receive_flags(lkb, ms); 394362306a36Sopenharmony_ci 394462306a36Sopenharmony_ci error = receive_convert_args(ls, lkb, ms); 394562306a36Sopenharmony_ci if (error) { 394662306a36Sopenharmony_ci send_convert_reply(r, lkb, error); 394762306a36Sopenharmony_ci goto out; 394862306a36Sopenharmony_ci } 394962306a36Sopenharmony_ci 395062306a36Sopenharmony_ci reply = !down_conversion(lkb); 395162306a36Sopenharmony_ci 395262306a36Sopenharmony_ci error = do_convert(r, lkb); 395362306a36Sopenharmony_ci if (reply) 395462306a36Sopenharmony_ci send_convert_reply(r, lkb, error); 395562306a36Sopenharmony_ci do_convert_effects(r, lkb, error); 395662306a36Sopenharmony_ci out: 395762306a36Sopenharmony_ci unlock_rsb(r); 395862306a36Sopenharmony_ci put_rsb(r); 395962306a36Sopenharmony_ci dlm_put_lkb(lkb); 396062306a36Sopenharmony_ci return 0; 396162306a36Sopenharmony_ci 396262306a36Sopenharmony_ci fail: 396362306a36Sopenharmony_ci setup_local_lkb(ls, ms); 396462306a36Sopenharmony_ci send_convert_reply(&ls->ls_local_rsb, &ls->ls_local_lkb, error); 396562306a36Sopenharmony_ci return error; 396662306a36Sopenharmony_ci} 396762306a36Sopenharmony_ci 396862306a36Sopenharmony_cistatic int receive_unlock(struct dlm_ls *ls, const struct dlm_message *ms) 396962306a36Sopenharmony_ci{ 397062306a36Sopenharmony_ci struct dlm_lkb *lkb; 397162306a36Sopenharmony_ci struct dlm_rsb *r; 397262306a36Sopenharmony_ci int error; 397362306a36Sopenharmony_ci 397462306a36Sopenharmony_ci error = find_lkb(ls, le32_to_cpu(ms->m_remid), &lkb); 397562306a36Sopenharmony_ci if (error) 397662306a36Sopenharmony_ci goto fail; 397762306a36Sopenharmony_ci 397862306a36Sopenharmony_ci if (lkb->lkb_remid != le32_to_cpu(ms->m_lkid)) { 397962306a36Sopenharmony_ci log_error(ls, "receive_unlock %x remid %x remote %d %x", 398062306a36Sopenharmony_ci lkb->lkb_id, lkb->lkb_remid, 398162306a36Sopenharmony_ci le32_to_cpu(ms->m_header.h_nodeid), 398262306a36Sopenharmony_ci le32_to_cpu(ms->m_lkid)); 398362306a36Sopenharmony_ci error = -ENOENT; 398462306a36Sopenharmony_ci dlm_put_lkb(lkb); 398562306a36Sopenharmony_ci goto fail; 398662306a36Sopenharmony_ci } 398762306a36Sopenharmony_ci 398862306a36Sopenharmony_ci r = lkb->lkb_resource; 398962306a36Sopenharmony_ci 399062306a36Sopenharmony_ci hold_rsb(r); 399162306a36Sopenharmony_ci lock_rsb(r); 399262306a36Sopenharmony_ci 399362306a36Sopenharmony_ci error = validate_message(lkb, ms); 399462306a36Sopenharmony_ci if (error) 399562306a36Sopenharmony_ci goto out; 399662306a36Sopenharmony_ci 399762306a36Sopenharmony_ci receive_flags(lkb, ms); 399862306a36Sopenharmony_ci 399962306a36Sopenharmony_ci error = receive_unlock_args(ls, lkb, ms); 400062306a36Sopenharmony_ci if (error) { 400162306a36Sopenharmony_ci send_unlock_reply(r, lkb, error); 400262306a36Sopenharmony_ci goto out; 400362306a36Sopenharmony_ci } 400462306a36Sopenharmony_ci 400562306a36Sopenharmony_ci error = do_unlock(r, lkb); 400662306a36Sopenharmony_ci send_unlock_reply(r, lkb, error); 400762306a36Sopenharmony_ci do_unlock_effects(r, lkb, error); 400862306a36Sopenharmony_ci out: 400962306a36Sopenharmony_ci unlock_rsb(r); 401062306a36Sopenharmony_ci put_rsb(r); 401162306a36Sopenharmony_ci dlm_put_lkb(lkb); 401262306a36Sopenharmony_ci return 0; 401362306a36Sopenharmony_ci 401462306a36Sopenharmony_ci fail: 401562306a36Sopenharmony_ci setup_local_lkb(ls, ms); 401662306a36Sopenharmony_ci send_unlock_reply(&ls->ls_local_rsb, &ls->ls_local_lkb, error); 401762306a36Sopenharmony_ci return error; 401862306a36Sopenharmony_ci} 401962306a36Sopenharmony_ci 402062306a36Sopenharmony_cistatic int receive_cancel(struct dlm_ls *ls, const struct dlm_message *ms) 402162306a36Sopenharmony_ci{ 402262306a36Sopenharmony_ci struct dlm_lkb *lkb; 402362306a36Sopenharmony_ci struct dlm_rsb *r; 402462306a36Sopenharmony_ci int error; 402562306a36Sopenharmony_ci 402662306a36Sopenharmony_ci error = find_lkb(ls, le32_to_cpu(ms->m_remid), &lkb); 402762306a36Sopenharmony_ci if (error) 402862306a36Sopenharmony_ci goto fail; 402962306a36Sopenharmony_ci 403062306a36Sopenharmony_ci receive_flags(lkb, ms); 403162306a36Sopenharmony_ci 403262306a36Sopenharmony_ci r = lkb->lkb_resource; 403362306a36Sopenharmony_ci 403462306a36Sopenharmony_ci hold_rsb(r); 403562306a36Sopenharmony_ci lock_rsb(r); 403662306a36Sopenharmony_ci 403762306a36Sopenharmony_ci error = validate_message(lkb, ms); 403862306a36Sopenharmony_ci if (error) 403962306a36Sopenharmony_ci goto out; 404062306a36Sopenharmony_ci 404162306a36Sopenharmony_ci error = do_cancel(r, lkb); 404262306a36Sopenharmony_ci send_cancel_reply(r, lkb, error); 404362306a36Sopenharmony_ci do_cancel_effects(r, lkb, error); 404462306a36Sopenharmony_ci out: 404562306a36Sopenharmony_ci unlock_rsb(r); 404662306a36Sopenharmony_ci put_rsb(r); 404762306a36Sopenharmony_ci dlm_put_lkb(lkb); 404862306a36Sopenharmony_ci return 0; 404962306a36Sopenharmony_ci 405062306a36Sopenharmony_ci fail: 405162306a36Sopenharmony_ci setup_local_lkb(ls, ms); 405262306a36Sopenharmony_ci send_cancel_reply(&ls->ls_local_rsb, &ls->ls_local_lkb, error); 405362306a36Sopenharmony_ci return error; 405462306a36Sopenharmony_ci} 405562306a36Sopenharmony_ci 405662306a36Sopenharmony_cistatic int receive_grant(struct dlm_ls *ls, const struct dlm_message *ms) 405762306a36Sopenharmony_ci{ 405862306a36Sopenharmony_ci struct dlm_lkb *lkb; 405962306a36Sopenharmony_ci struct dlm_rsb *r; 406062306a36Sopenharmony_ci int error; 406162306a36Sopenharmony_ci 406262306a36Sopenharmony_ci error = find_lkb(ls, le32_to_cpu(ms->m_remid), &lkb); 406362306a36Sopenharmony_ci if (error) 406462306a36Sopenharmony_ci return error; 406562306a36Sopenharmony_ci 406662306a36Sopenharmony_ci r = lkb->lkb_resource; 406762306a36Sopenharmony_ci 406862306a36Sopenharmony_ci hold_rsb(r); 406962306a36Sopenharmony_ci lock_rsb(r); 407062306a36Sopenharmony_ci 407162306a36Sopenharmony_ci error = validate_message(lkb, ms); 407262306a36Sopenharmony_ci if (error) 407362306a36Sopenharmony_ci goto out; 407462306a36Sopenharmony_ci 407562306a36Sopenharmony_ci receive_flags_reply(lkb, ms, false); 407662306a36Sopenharmony_ci if (is_altmode(lkb)) 407762306a36Sopenharmony_ci munge_altmode(lkb, ms); 407862306a36Sopenharmony_ci grant_lock_pc(r, lkb, ms); 407962306a36Sopenharmony_ci queue_cast(r, lkb, 0); 408062306a36Sopenharmony_ci out: 408162306a36Sopenharmony_ci unlock_rsb(r); 408262306a36Sopenharmony_ci put_rsb(r); 408362306a36Sopenharmony_ci dlm_put_lkb(lkb); 408462306a36Sopenharmony_ci return 0; 408562306a36Sopenharmony_ci} 408662306a36Sopenharmony_ci 408762306a36Sopenharmony_cistatic int receive_bast(struct dlm_ls *ls, const struct dlm_message *ms) 408862306a36Sopenharmony_ci{ 408962306a36Sopenharmony_ci struct dlm_lkb *lkb; 409062306a36Sopenharmony_ci struct dlm_rsb *r; 409162306a36Sopenharmony_ci int error; 409262306a36Sopenharmony_ci 409362306a36Sopenharmony_ci error = find_lkb(ls, le32_to_cpu(ms->m_remid), &lkb); 409462306a36Sopenharmony_ci if (error) 409562306a36Sopenharmony_ci return error; 409662306a36Sopenharmony_ci 409762306a36Sopenharmony_ci r = lkb->lkb_resource; 409862306a36Sopenharmony_ci 409962306a36Sopenharmony_ci hold_rsb(r); 410062306a36Sopenharmony_ci lock_rsb(r); 410162306a36Sopenharmony_ci 410262306a36Sopenharmony_ci error = validate_message(lkb, ms); 410362306a36Sopenharmony_ci if (error) 410462306a36Sopenharmony_ci goto out; 410562306a36Sopenharmony_ci 410662306a36Sopenharmony_ci queue_bast(r, lkb, le32_to_cpu(ms->m_bastmode)); 410762306a36Sopenharmony_ci lkb->lkb_highbast = le32_to_cpu(ms->m_bastmode); 410862306a36Sopenharmony_ci out: 410962306a36Sopenharmony_ci unlock_rsb(r); 411062306a36Sopenharmony_ci put_rsb(r); 411162306a36Sopenharmony_ci dlm_put_lkb(lkb); 411262306a36Sopenharmony_ci return 0; 411362306a36Sopenharmony_ci} 411462306a36Sopenharmony_ci 411562306a36Sopenharmony_cistatic void receive_lookup(struct dlm_ls *ls, const struct dlm_message *ms) 411662306a36Sopenharmony_ci{ 411762306a36Sopenharmony_ci int len, error, ret_nodeid, from_nodeid, our_nodeid; 411862306a36Sopenharmony_ci 411962306a36Sopenharmony_ci from_nodeid = le32_to_cpu(ms->m_header.h_nodeid); 412062306a36Sopenharmony_ci our_nodeid = dlm_our_nodeid(); 412162306a36Sopenharmony_ci 412262306a36Sopenharmony_ci len = receive_extralen(ms); 412362306a36Sopenharmony_ci 412462306a36Sopenharmony_ci error = dlm_master_lookup(ls, from_nodeid, ms->m_extra, len, 0, 412562306a36Sopenharmony_ci &ret_nodeid, NULL); 412662306a36Sopenharmony_ci 412762306a36Sopenharmony_ci /* Optimization: we're master so treat lookup as a request */ 412862306a36Sopenharmony_ci if (!error && ret_nodeid == our_nodeid) { 412962306a36Sopenharmony_ci receive_request(ls, ms); 413062306a36Sopenharmony_ci return; 413162306a36Sopenharmony_ci } 413262306a36Sopenharmony_ci send_lookup_reply(ls, ms, ret_nodeid, error); 413362306a36Sopenharmony_ci} 413462306a36Sopenharmony_ci 413562306a36Sopenharmony_cistatic void receive_remove(struct dlm_ls *ls, const struct dlm_message *ms) 413662306a36Sopenharmony_ci{ 413762306a36Sopenharmony_ci char name[DLM_RESNAME_MAXLEN+1]; 413862306a36Sopenharmony_ci struct dlm_rsb *r; 413962306a36Sopenharmony_ci uint32_t hash, b; 414062306a36Sopenharmony_ci int rv, len, dir_nodeid, from_nodeid; 414162306a36Sopenharmony_ci 414262306a36Sopenharmony_ci from_nodeid = le32_to_cpu(ms->m_header.h_nodeid); 414362306a36Sopenharmony_ci 414462306a36Sopenharmony_ci len = receive_extralen(ms); 414562306a36Sopenharmony_ci 414662306a36Sopenharmony_ci if (len > DLM_RESNAME_MAXLEN) { 414762306a36Sopenharmony_ci log_error(ls, "receive_remove from %d bad len %d", 414862306a36Sopenharmony_ci from_nodeid, len); 414962306a36Sopenharmony_ci return; 415062306a36Sopenharmony_ci } 415162306a36Sopenharmony_ci 415262306a36Sopenharmony_ci dir_nodeid = dlm_hash2nodeid(ls, le32_to_cpu(ms->m_hash)); 415362306a36Sopenharmony_ci if (dir_nodeid != dlm_our_nodeid()) { 415462306a36Sopenharmony_ci log_error(ls, "receive_remove from %d bad nodeid %d", 415562306a36Sopenharmony_ci from_nodeid, dir_nodeid); 415662306a36Sopenharmony_ci return; 415762306a36Sopenharmony_ci } 415862306a36Sopenharmony_ci 415962306a36Sopenharmony_ci /* Look for name on rsbtbl.toss, if it's there, kill it. 416062306a36Sopenharmony_ci If it's on rsbtbl.keep, it's being used, and we should ignore this 416162306a36Sopenharmony_ci message. This is an expected race between the dir node sending a 416262306a36Sopenharmony_ci request to the master node at the same time as the master node sends 416362306a36Sopenharmony_ci a remove to the dir node. The resolution to that race is for the 416462306a36Sopenharmony_ci dir node to ignore the remove message, and the master node to 416562306a36Sopenharmony_ci recreate the master rsb when it gets a request from the dir node for 416662306a36Sopenharmony_ci an rsb it doesn't have. */ 416762306a36Sopenharmony_ci 416862306a36Sopenharmony_ci memset(name, 0, sizeof(name)); 416962306a36Sopenharmony_ci memcpy(name, ms->m_extra, len); 417062306a36Sopenharmony_ci 417162306a36Sopenharmony_ci hash = jhash(name, len, 0); 417262306a36Sopenharmony_ci b = hash & (ls->ls_rsbtbl_size - 1); 417362306a36Sopenharmony_ci 417462306a36Sopenharmony_ci spin_lock(&ls->ls_rsbtbl[b].lock); 417562306a36Sopenharmony_ci 417662306a36Sopenharmony_ci rv = dlm_search_rsb_tree(&ls->ls_rsbtbl[b].toss, name, len, &r); 417762306a36Sopenharmony_ci if (rv) { 417862306a36Sopenharmony_ci /* verify the rsb is on keep list per comment above */ 417962306a36Sopenharmony_ci rv = dlm_search_rsb_tree(&ls->ls_rsbtbl[b].keep, name, len, &r); 418062306a36Sopenharmony_ci if (rv) { 418162306a36Sopenharmony_ci /* should not happen */ 418262306a36Sopenharmony_ci log_error(ls, "receive_remove from %d not found %s", 418362306a36Sopenharmony_ci from_nodeid, name); 418462306a36Sopenharmony_ci spin_unlock(&ls->ls_rsbtbl[b].lock); 418562306a36Sopenharmony_ci return; 418662306a36Sopenharmony_ci } 418762306a36Sopenharmony_ci if (r->res_master_nodeid != from_nodeid) { 418862306a36Sopenharmony_ci /* should not happen */ 418962306a36Sopenharmony_ci log_error(ls, "receive_remove keep from %d master %d", 419062306a36Sopenharmony_ci from_nodeid, r->res_master_nodeid); 419162306a36Sopenharmony_ci dlm_print_rsb(r); 419262306a36Sopenharmony_ci spin_unlock(&ls->ls_rsbtbl[b].lock); 419362306a36Sopenharmony_ci return; 419462306a36Sopenharmony_ci } 419562306a36Sopenharmony_ci 419662306a36Sopenharmony_ci log_debug(ls, "receive_remove from %d master %d first %x %s", 419762306a36Sopenharmony_ci from_nodeid, r->res_master_nodeid, r->res_first_lkid, 419862306a36Sopenharmony_ci name); 419962306a36Sopenharmony_ci spin_unlock(&ls->ls_rsbtbl[b].lock); 420062306a36Sopenharmony_ci return; 420162306a36Sopenharmony_ci } 420262306a36Sopenharmony_ci 420362306a36Sopenharmony_ci if (r->res_master_nodeid != from_nodeid) { 420462306a36Sopenharmony_ci log_error(ls, "receive_remove toss from %d master %d", 420562306a36Sopenharmony_ci from_nodeid, r->res_master_nodeid); 420662306a36Sopenharmony_ci dlm_print_rsb(r); 420762306a36Sopenharmony_ci spin_unlock(&ls->ls_rsbtbl[b].lock); 420862306a36Sopenharmony_ci return; 420962306a36Sopenharmony_ci } 421062306a36Sopenharmony_ci 421162306a36Sopenharmony_ci if (kref_put(&r->res_ref, kill_rsb)) { 421262306a36Sopenharmony_ci rb_erase(&r->res_hashnode, &ls->ls_rsbtbl[b].toss); 421362306a36Sopenharmony_ci spin_unlock(&ls->ls_rsbtbl[b].lock); 421462306a36Sopenharmony_ci dlm_free_rsb(r); 421562306a36Sopenharmony_ci } else { 421662306a36Sopenharmony_ci log_error(ls, "receive_remove from %d rsb ref error", 421762306a36Sopenharmony_ci from_nodeid); 421862306a36Sopenharmony_ci dlm_print_rsb(r); 421962306a36Sopenharmony_ci spin_unlock(&ls->ls_rsbtbl[b].lock); 422062306a36Sopenharmony_ci } 422162306a36Sopenharmony_ci} 422262306a36Sopenharmony_ci 422362306a36Sopenharmony_cistatic void receive_purge(struct dlm_ls *ls, const struct dlm_message *ms) 422462306a36Sopenharmony_ci{ 422562306a36Sopenharmony_ci do_purge(ls, le32_to_cpu(ms->m_nodeid), le32_to_cpu(ms->m_pid)); 422662306a36Sopenharmony_ci} 422762306a36Sopenharmony_ci 422862306a36Sopenharmony_cistatic int receive_request_reply(struct dlm_ls *ls, 422962306a36Sopenharmony_ci const struct dlm_message *ms) 423062306a36Sopenharmony_ci{ 423162306a36Sopenharmony_ci struct dlm_lkb *lkb; 423262306a36Sopenharmony_ci struct dlm_rsb *r; 423362306a36Sopenharmony_ci int error, mstype, result; 423462306a36Sopenharmony_ci int from_nodeid = le32_to_cpu(ms->m_header.h_nodeid); 423562306a36Sopenharmony_ci 423662306a36Sopenharmony_ci error = find_lkb(ls, le32_to_cpu(ms->m_remid), &lkb); 423762306a36Sopenharmony_ci if (error) 423862306a36Sopenharmony_ci return error; 423962306a36Sopenharmony_ci 424062306a36Sopenharmony_ci r = lkb->lkb_resource; 424162306a36Sopenharmony_ci hold_rsb(r); 424262306a36Sopenharmony_ci lock_rsb(r); 424362306a36Sopenharmony_ci 424462306a36Sopenharmony_ci error = validate_message(lkb, ms); 424562306a36Sopenharmony_ci if (error) 424662306a36Sopenharmony_ci goto out; 424762306a36Sopenharmony_ci 424862306a36Sopenharmony_ci mstype = lkb->lkb_wait_type; 424962306a36Sopenharmony_ci error = remove_from_waiters(lkb, DLM_MSG_REQUEST_REPLY); 425062306a36Sopenharmony_ci if (error) { 425162306a36Sopenharmony_ci log_error(ls, "receive_request_reply %x remote %d %x result %d", 425262306a36Sopenharmony_ci lkb->lkb_id, from_nodeid, le32_to_cpu(ms->m_lkid), 425362306a36Sopenharmony_ci from_dlm_errno(le32_to_cpu(ms->m_result))); 425462306a36Sopenharmony_ci dlm_dump_rsb(r); 425562306a36Sopenharmony_ci goto out; 425662306a36Sopenharmony_ci } 425762306a36Sopenharmony_ci 425862306a36Sopenharmony_ci /* Optimization: the dir node was also the master, so it took our 425962306a36Sopenharmony_ci lookup as a request and sent request reply instead of lookup reply */ 426062306a36Sopenharmony_ci if (mstype == DLM_MSG_LOOKUP) { 426162306a36Sopenharmony_ci r->res_master_nodeid = from_nodeid; 426262306a36Sopenharmony_ci r->res_nodeid = from_nodeid; 426362306a36Sopenharmony_ci lkb->lkb_nodeid = from_nodeid; 426462306a36Sopenharmony_ci } 426562306a36Sopenharmony_ci 426662306a36Sopenharmony_ci /* this is the value returned from do_request() on the master */ 426762306a36Sopenharmony_ci result = from_dlm_errno(le32_to_cpu(ms->m_result)); 426862306a36Sopenharmony_ci 426962306a36Sopenharmony_ci switch (result) { 427062306a36Sopenharmony_ci case -EAGAIN: 427162306a36Sopenharmony_ci /* request would block (be queued) on remote master */ 427262306a36Sopenharmony_ci queue_cast(r, lkb, -EAGAIN); 427362306a36Sopenharmony_ci confirm_master(r, -EAGAIN); 427462306a36Sopenharmony_ci unhold_lkb(lkb); /* undoes create_lkb() */ 427562306a36Sopenharmony_ci break; 427662306a36Sopenharmony_ci 427762306a36Sopenharmony_ci case -EINPROGRESS: 427862306a36Sopenharmony_ci case 0: 427962306a36Sopenharmony_ci /* request was queued or granted on remote master */ 428062306a36Sopenharmony_ci receive_flags_reply(lkb, ms, false); 428162306a36Sopenharmony_ci lkb->lkb_remid = le32_to_cpu(ms->m_lkid); 428262306a36Sopenharmony_ci if (is_altmode(lkb)) 428362306a36Sopenharmony_ci munge_altmode(lkb, ms); 428462306a36Sopenharmony_ci if (result) { 428562306a36Sopenharmony_ci add_lkb(r, lkb, DLM_LKSTS_WAITING); 428662306a36Sopenharmony_ci } else { 428762306a36Sopenharmony_ci grant_lock_pc(r, lkb, ms); 428862306a36Sopenharmony_ci queue_cast(r, lkb, 0); 428962306a36Sopenharmony_ci } 429062306a36Sopenharmony_ci confirm_master(r, result); 429162306a36Sopenharmony_ci break; 429262306a36Sopenharmony_ci 429362306a36Sopenharmony_ci case -EBADR: 429462306a36Sopenharmony_ci case -ENOTBLK: 429562306a36Sopenharmony_ci /* find_rsb failed to find rsb or rsb wasn't master */ 429662306a36Sopenharmony_ci log_limit(ls, "receive_request_reply %x from %d %d " 429762306a36Sopenharmony_ci "master %d dir %d first %x %s", lkb->lkb_id, 429862306a36Sopenharmony_ci from_nodeid, result, r->res_master_nodeid, 429962306a36Sopenharmony_ci r->res_dir_nodeid, r->res_first_lkid, r->res_name); 430062306a36Sopenharmony_ci 430162306a36Sopenharmony_ci if (r->res_dir_nodeid != dlm_our_nodeid() && 430262306a36Sopenharmony_ci r->res_master_nodeid != dlm_our_nodeid()) { 430362306a36Sopenharmony_ci /* cause _request_lock->set_master->send_lookup */ 430462306a36Sopenharmony_ci r->res_master_nodeid = 0; 430562306a36Sopenharmony_ci r->res_nodeid = -1; 430662306a36Sopenharmony_ci lkb->lkb_nodeid = -1; 430762306a36Sopenharmony_ci } 430862306a36Sopenharmony_ci 430962306a36Sopenharmony_ci if (is_overlap(lkb)) { 431062306a36Sopenharmony_ci /* we'll ignore error in cancel/unlock reply */ 431162306a36Sopenharmony_ci queue_cast_overlap(r, lkb); 431262306a36Sopenharmony_ci confirm_master(r, result); 431362306a36Sopenharmony_ci unhold_lkb(lkb); /* undoes create_lkb() */ 431462306a36Sopenharmony_ci } else { 431562306a36Sopenharmony_ci _request_lock(r, lkb); 431662306a36Sopenharmony_ci 431762306a36Sopenharmony_ci if (r->res_master_nodeid == dlm_our_nodeid()) 431862306a36Sopenharmony_ci confirm_master(r, 0); 431962306a36Sopenharmony_ci } 432062306a36Sopenharmony_ci break; 432162306a36Sopenharmony_ci 432262306a36Sopenharmony_ci default: 432362306a36Sopenharmony_ci log_error(ls, "receive_request_reply %x error %d", 432462306a36Sopenharmony_ci lkb->lkb_id, result); 432562306a36Sopenharmony_ci } 432662306a36Sopenharmony_ci 432762306a36Sopenharmony_ci if ((result == 0 || result == -EINPROGRESS) && 432862306a36Sopenharmony_ci test_and_clear_bit(DLM_IFL_OVERLAP_UNLOCK_BIT, &lkb->lkb_iflags)) { 432962306a36Sopenharmony_ci log_debug(ls, "receive_request_reply %x result %d unlock", 433062306a36Sopenharmony_ci lkb->lkb_id, result); 433162306a36Sopenharmony_ci clear_bit(DLM_IFL_OVERLAP_CANCEL_BIT, &lkb->lkb_iflags); 433262306a36Sopenharmony_ci send_unlock(r, lkb); 433362306a36Sopenharmony_ci } else if ((result == -EINPROGRESS) && 433462306a36Sopenharmony_ci test_and_clear_bit(DLM_IFL_OVERLAP_CANCEL_BIT, 433562306a36Sopenharmony_ci &lkb->lkb_iflags)) { 433662306a36Sopenharmony_ci log_debug(ls, "receive_request_reply %x cancel", lkb->lkb_id); 433762306a36Sopenharmony_ci clear_bit(DLM_IFL_OVERLAP_UNLOCK_BIT, &lkb->lkb_iflags); 433862306a36Sopenharmony_ci send_cancel(r, lkb); 433962306a36Sopenharmony_ci } else { 434062306a36Sopenharmony_ci clear_bit(DLM_IFL_OVERLAP_CANCEL_BIT, &lkb->lkb_iflags); 434162306a36Sopenharmony_ci clear_bit(DLM_IFL_OVERLAP_UNLOCK_BIT, &lkb->lkb_iflags); 434262306a36Sopenharmony_ci } 434362306a36Sopenharmony_ci out: 434462306a36Sopenharmony_ci unlock_rsb(r); 434562306a36Sopenharmony_ci put_rsb(r); 434662306a36Sopenharmony_ci dlm_put_lkb(lkb); 434762306a36Sopenharmony_ci return 0; 434862306a36Sopenharmony_ci} 434962306a36Sopenharmony_ci 435062306a36Sopenharmony_cistatic void __receive_convert_reply(struct dlm_rsb *r, struct dlm_lkb *lkb, 435162306a36Sopenharmony_ci const struct dlm_message *ms, bool local) 435262306a36Sopenharmony_ci{ 435362306a36Sopenharmony_ci /* this is the value returned from do_convert() on the master */ 435462306a36Sopenharmony_ci switch (from_dlm_errno(le32_to_cpu(ms->m_result))) { 435562306a36Sopenharmony_ci case -EAGAIN: 435662306a36Sopenharmony_ci /* convert would block (be queued) on remote master */ 435762306a36Sopenharmony_ci queue_cast(r, lkb, -EAGAIN); 435862306a36Sopenharmony_ci break; 435962306a36Sopenharmony_ci 436062306a36Sopenharmony_ci case -EDEADLK: 436162306a36Sopenharmony_ci receive_flags_reply(lkb, ms, local); 436262306a36Sopenharmony_ci revert_lock_pc(r, lkb); 436362306a36Sopenharmony_ci queue_cast(r, lkb, -EDEADLK); 436462306a36Sopenharmony_ci break; 436562306a36Sopenharmony_ci 436662306a36Sopenharmony_ci case -EINPROGRESS: 436762306a36Sopenharmony_ci /* convert was queued on remote master */ 436862306a36Sopenharmony_ci receive_flags_reply(lkb, ms, local); 436962306a36Sopenharmony_ci if (is_demoted(lkb)) 437062306a36Sopenharmony_ci munge_demoted(lkb); 437162306a36Sopenharmony_ci del_lkb(r, lkb); 437262306a36Sopenharmony_ci add_lkb(r, lkb, DLM_LKSTS_CONVERT); 437362306a36Sopenharmony_ci break; 437462306a36Sopenharmony_ci 437562306a36Sopenharmony_ci case 0: 437662306a36Sopenharmony_ci /* convert was granted on remote master */ 437762306a36Sopenharmony_ci receive_flags_reply(lkb, ms, local); 437862306a36Sopenharmony_ci if (is_demoted(lkb)) 437962306a36Sopenharmony_ci munge_demoted(lkb); 438062306a36Sopenharmony_ci grant_lock_pc(r, lkb, ms); 438162306a36Sopenharmony_ci queue_cast(r, lkb, 0); 438262306a36Sopenharmony_ci break; 438362306a36Sopenharmony_ci 438462306a36Sopenharmony_ci default: 438562306a36Sopenharmony_ci log_error(r->res_ls, "receive_convert_reply %x remote %d %x %d", 438662306a36Sopenharmony_ci lkb->lkb_id, le32_to_cpu(ms->m_header.h_nodeid), 438762306a36Sopenharmony_ci le32_to_cpu(ms->m_lkid), 438862306a36Sopenharmony_ci from_dlm_errno(le32_to_cpu(ms->m_result))); 438962306a36Sopenharmony_ci dlm_print_rsb(r); 439062306a36Sopenharmony_ci dlm_print_lkb(lkb); 439162306a36Sopenharmony_ci } 439262306a36Sopenharmony_ci} 439362306a36Sopenharmony_ci 439462306a36Sopenharmony_cistatic void _receive_convert_reply(struct dlm_lkb *lkb, 439562306a36Sopenharmony_ci const struct dlm_message *ms, bool local) 439662306a36Sopenharmony_ci{ 439762306a36Sopenharmony_ci struct dlm_rsb *r = lkb->lkb_resource; 439862306a36Sopenharmony_ci int error; 439962306a36Sopenharmony_ci 440062306a36Sopenharmony_ci hold_rsb(r); 440162306a36Sopenharmony_ci lock_rsb(r); 440262306a36Sopenharmony_ci 440362306a36Sopenharmony_ci error = validate_message(lkb, ms); 440462306a36Sopenharmony_ci if (error) 440562306a36Sopenharmony_ci goto out; 440662306a36Sopenharmony_ci 440762306a36Sopenharmony_ci /* local reply can happen with waiters_mutex held */ 440862306a36Sopenharmony_ci error = remove_from_waiters_ms(lkb, ms, local); 440962306a36Sopenharmony_ci if (error) 441062306a36Sopenharmony_ci goto out; 441162306a36Sopenharmony_ci 441262306a36Sopenharmony_ci __receive_convert_reply(r, lkb, ms, local); 441362306a36Sopenharmony_ci out: 441462306a36Sopenharmony_ci unlock_rsb(r); 441562306a36Sopenharmony_ci put_rsb(r); 441662306a36Sopenharmony_ci} 441762306a36Sopenharmony_ci 441862306a36Sopenharmony_cistatic int receive_convert_reply(struct dlm_ls *ls, 441962306a36Sopenharmony_ci const struct dlm_message *ms) 442062306a36Sopenharmony_ci{ 442162306a36Sopenharmony_ci struct dlm_lkb *lkb; 442262306a36Sopenharmony_ci int error; 442362306a36Sopenharmony_ci 442462306a36Sopenharmony_ci error = find_lkb(ls, le32_to_cpu(ms->m_remid), &lkb); 442562306a36Sopenharmony_ci if (error) 442662306a36Sopenharmony_ci return error; 442762306a36Sopenharmony_ci 442862306a36Sopenharmony_ci _receive_convert_reply(lkb, ms, false); 442962306a36Sopenharmony_ci dlm_put_lkb(lkb); 443062306a36Sopenharmony_ci return 0; 443162306a36Sopenharmony_ci} 443262306a36Sopenharmony_ci 443362306a36Sopenharmony_cistatic void _receive_unlock_reply(struct dlm_lkb *lkb, 443462306a36Sopenharmony_ci const struct dlm_message *ms, bool local) 443562306a36Sopenharmony_ci{ 443662306a36Sopenharmony_ci struct dlm_rsb *r = lkb->lkb_resource; 443762306a36Sopenharmony_ci int error; 443862306a36Sopenharmony_ci 443962306a36Sopenharmony_ci hold_rsb(r); 444062306a36Sopenharmony_ci lock_rsb(r); 444162306a36Sopenharmony_ci 444262306a36Sopenharmony_ci error = validate_message(lkb, ms); 444362306a36Sopenharmony_ci if (error) 444462306a36Sopenharmony_ci goto out; 444562306a36Sopenharmony_ci 444662306a36Sopenharmony_ci /* local reply can happen with waiters_mutex held */ 444762306a36Sopenharmony_ci error = remove_from_waiters_ms(lkb, ms, local); 444862306a36Sopenharmony_ci if (error) 444962306a36Sopenharmony_ci goto out; 445062306a36Sopenharmony_ci 445162306a36Sopenharmony_ci /* this is the value returned from do_unlock() on the master */ 445262306a36Sopenharmony_ci 445362306a36Sopenharmony_ci switch (from_dlm_errno(le32_to_cpu(ms->m_result))) { 445462306a36Sopenharmony_ci case -DLM_EUNLOCK: 445562306a36Sopenharmony_ci receive_flags_reply(lkb, ms, local); 445662306a36Sopenharmony_ci remove_lock_pc(r, lkb); 445762306a36Sopenharmony_ci queue_cast(r, lkb, -DLM_EUNLOCK); 445862306a36Sopenharmony_ci break; 445962306a36Sopenharmony_ci case -ENOENT: 446062306a36Sopenharmony_ci break; 446162306a36Sopenharmony_ci default: 446262306a36Sopenharmony_ci log_error(r->res_ls, "receive_unlock_reply %x error %d", 446362306a36Sopenharmony_ci lkb->lkb_id, from_dlm_errno(le32_to_cpu(ms->m_result))); 446462306a36Sopenharmony_ci } 446562306a36Sopenharmony_ci out: 446662306a36Sopenharmony_ci unlock_rsb(r); 446762306a36Sopenharmony_ci put_rsb(r); 446862306a36Sopenharmony_ci} 446962306a36Sopenharmony_ci 447062306a36Sopenharmony_cistatic int receive_unlock_reply(struct dlm_ls *ls, 447162306a36Sopenharmony_ci const struct dlm_message *ms) 447262306a36Sopenharmony_ci{ 447362306a36Sopenharmony_ci struct dlm_lkb *lkb; 447462306a36Sopenharmony_ci int error; 447562306a36Sopenharmony_ci 447662306a36Sopenharmony_ci error = find_lkb(ls, le32_to_cpu(ms->m_remid), &lkb); 447762306a36Sopenharmony_ci if (error) 447862306a36Sopenharmony_ci return error; 447962306a36Sopenharmony_ci 448062306a36Sopenharmony_ci _receive_unlock_reply(lkb, ms, false); 448162306a36Sopenharmony_ci dlm_put_lkb(lkb); 448262306a36Sopenharmony_ci return 0; 448362306a36Sopenharmony_ci} 448462306a36Sopenharmony_ci 448562306a36Sopenharmony_cistatic void _receive_cancel_reply(struct dlm_lkb *lkb, 448662306a36Sopenharmony_ci const struct dlm_message *ms, bool local) 448762306a36Sopenharmony_ci{ 448862306a36Sopenharmony_ci struct dlm_rsb *r = lkb->lkb_resource; 448962306a36Sopenharmony_ci int error; 449062306a36Sopenharmony_ci 449162306a36Sopenharmony_ci hold_rsb(r); 449262306a36Sopenharmony_ci lock_rsb(r); 449362306a36Sopenharmony_ci 449462306a36Sopenharmony_ci error = validate_message(lkb, ms); 449562306a36Sopenharmony_ci if (error) 449662306a36Sopenharmony_ci goto out; 449762306a36Sopenharmony_ci 449862306a36Sopenharmony_ci /* local reply can happen with waiters_mutex held */ 449962306a36Sopenharmony_ci error = remove_from_waiters_ms(lkb, ms, local); 450062306a36Sopenharmony_ci if (error) 450162306a36Sopenharmony_ci goto out; 450262306a36Sopenharmony_ci 450362306a36Sopenharmony_ci /* this is the value returned from do_cancel() on the master */ 450462306a36Sopenharmony_ci 450562306a36Sopenharmony_ci switch (from_dlm_errno(le32_to_cpu(ms->m_result))) { 450662306a36Sopenharmony_ci case -DLM_ECANCEL: 450762306a36Sopenharmony_ci receive_flags_reply(lkb, ms, local); 450862306a36Sopenharmony_ci revert_lock_pc(r, lkb); 450962306a36Sopenharmony_ci queue_cast(r, lkb, -DLM_ECANCEL); 451062306a36Sopenharmony_ci break; 451162306a36Sopenharmony_ci case 0: 451262306a36Sopenharmony_ci break; 451362306a36Sopenharmony_ci default: 451462306a36Sopenharmony_ci log_error(r->res_ls, "receive_cancel_reply %x error %d", 451562306a36Sopenharmony_ci lkb->lkb_id, 451662306a36Sopenharmony_ci from_dlm_errno(le32_to_cpu(ms->m_result))); 451762306a36Sopenharmony_ci } 451862306a36Sopenharmony_ci out: 451962306a36Sopenharmony_ci unlock_rsb(r); 452062306a36Sopenharmony_ci put_rsb(r); 452162306a36Sopenharmony_ci} 452262306a36Sopenharmony_ci 452362306a36Sopenharmony_cistatic int receive_cancel_reply(struct dlm_ls *ls, 452462306a36Sopenharmony_ci const struct dlm_message *ms) 452562306a36Sopenharmony_ci{ 452662306a36Sopenharmony_ci struct dlm_lkb *lkb; 452762306a36Sopenharmony_ci int error; 452862306a36Sopenharmony_ci 452962306a36Sopenharmony_ci error = find_lkb(ls, le32_to_cpu(ms->m_remid), &lkb); 453062306a36Sopenharmony_ci if (error) 453162306a36Sopenharmony_ci return error; 453262306a36Sopenharmony_ci 453362306a36Sopenharmony_ci _receive_cancel_reply(lkb, ms, false); 453462306a36Sopenharmony_ci dlm_put_lkb(lkb); 453562306a36Sopenharmony_ci return 0; 453662306a36Sopenharmony_ci} 453762306a36Sopenharmony_ci 453862306a36Sopenharmony_cistatic void receive_lookup_reply(struct dlm_ls *ls, 453962306a36Sopenharmony_ci const struct dlm_message *ms) 454062306a36Sopenharmony_ci{ 454162306a36Sopenharmony_ci struct dlm_lkb *lkb; 454262306a36Sopenharmony_ci struct dlm_rsb *r; 454362306a36Sopenharmony_ci int error, ret_nodeid; 454462306a36Sopenharmony_ci int do_lookup_list = 0; 454562306a36Sopenharmony_ci 454662306a36Sopenharmony_ci error = find_lkb(ls, le32_to_cpu(ms->m_lkid), &lkb); 454762306a36Sopenharmony_ci if (error) { 454862306a36Sopenharmony_ci log_error(ls, "%s no lkid %x", __func__, 454962306a36Sopenharmony_ci le32_to_cpu(ms->m_lkid)); 455062306a36Sopenharmony_ci return; 455162306a36Sopenharmony_ci } 455262306a36Sopenharmony_ci 455362306a36Sopenharmony_ci /* ms->m_result is the value returned by dlm_master_lookup on dir node 455462306a36Sopenharmony_ci FIXME: will a non-zero error ever be returned? */ 455562306a36Sopenharmony_ci 455662306a36Sopenharmony_ci r = lkb->lkb_resource; 455762306a36Sopenharmony_ci hold_rsb(r); 455862306a36Sopenharmony_ci lock_rsb(r); 455962306a36Sopenharmony_ci 456062306a36Sopenharmony_ci error = remove_from_waiters(lkb, DLM_MSG_LOOKUP_REPLY); 456162306a36Sopenharmony_ci if (error) 456262306a36Sopenharmony_ci goto out; 456362306a36Sopenharmony_ci 456462306a36Sopenharmony_ci ret_nodeid = le32_to_cpu(ms->m_nodeid); 456562306a36Sopenharmony_ci 456662306a36Sopenharmony_ci /* We sometimes receive a request from the dir node for this 456762306a36Sopenharmony_ci rsb before we've received the dir node's loookup_reply for it. 456862306a36Sopenharmony_ci The request from the dir node implies we're the master, so we set 456962306a36Sopenharmony_ci ourself as master in receive_request_reply, and verify here that 457062306a36Sopenharmony_ci we are indeed the master. */ 457162306a36Sopenharmony_ci 457262306a36Sopenharmony_ci if (r->res_master_nodeid && (r->res_master_nodeid != ret_nodeid)) { 457362306a36Sopenharmony_ci /* This should never happen */ 457462306a36Sopenharmony_ci log_error(ls, "receive_lookup_reply %x from %d ret %d " 457562306a36Sopenharmony_ci "master %d dir %d our %d first %x %s", 457662306a36Sopenharmony_ci lkb->lkb_id, le32_to_cpu(ms->m_header.h_nodeid), 457762306a36Sopenharmony_ci ret_nodeid, r->res_master_nodeid, r->res_dir_nodeid, 457862306a36Sopenharmony_ci dlm_our_nodeid(), r->res_first_lkid, r->res_name); 457962306a36Sopenharmony_ci } 458062306a36Sopenharmony_ci 458162306a36Sopenharmony_ci if (ret_nodeid == dlm_our_nodeid()) { 458262306a36Sopenharmony_ci r->res_master_nodeid = ret_nodeid; 458362306a36Sopenharmony_ci r->res_nodeid = 0; 458462306a36Sopenharmony_ci do_lookup_list = 1; 458562306a36Sopenharmony_ci r->res_first_lkid = 0; 458662306a36Sopenharmony_ci } else if (ret_nodeid == -1) { 458762306a36Sopenharmony_ci /* the remote node doesn't believe it's the dir node */ 458862306a36Sopenharmony_ci log_error(ls, "receive_lookup_reply %x from %d bad ret_nodeid", 458962306a36Sopenharmony_ci lkb->lkb_id, le32_to_cpu(ms->m_header.h_nodeid)); 459062306a36Sopenharmony_ci r->res_master_nodeid = 0; 459162306a36Sopenharmony_ci r->res_nodeid = -1; 459262306a36Sopenharmony_ci lkb->lkb_nodeid = -1; 459362306a36Sopenharmony_ci } else { 459462306a36Sopenharmony_ci /* set_master() will set lkb_nodeid from r */ 459562306a36Sopenharmony_ci r->res_master_nodeid = ret_nodeid; 459662306a36Sopenharmony_ci r->res_nodeid = ret_nodeid; 459762306a36Sopenharmony_ci } 459862306a36Sopenharmony_ci 459962306a36Sopenharmony_ci if (is_overlap(lkb)) { 460062306a36Sopenharmony_ci log_debug(ls, "receive_lookup_reply %x unlock %x", 460162306a36Sopenharmony_ci lkb->lkb_id, dlm_iflags_val(lkb)); 460262306a36Sopenharmony_ci queue_cast_overlap(r, lkb); 460362306a36Sopenharmony_ci unhold_lkb(lkb); /* undoes create_lkb() */ 460462306a36Sopenharmony_ci goto out_list; 460562306a36Sopenharmony_ci } 460662306a36Sopenharmony_ci 460762306a36Sopenharmony_ci _request_lock(r, lkb); 460862306a36Sopenharmony_ci 460962306a36Sopenharmony_ci out_list: 461062306a36Sopenharmony_ci if (do_lookup_list) 461162306a36Sopenharmony_ci process_lookup_list(r); 461262306a36Sopenharmony_ci out: 461362306a36Sopenharmony_ci unlock_rsb(r); 461462306a36Sopenharmony_ci put_rsb(r); 461562306a36Sopenharmony_ci dlm_put_lkb(lkb); 461662306a36Sopenharmony_ci} 461762306a36Sopenharmony_ci 461862306a36Sopenharmony_cistatic void _receive_message(struct dlm_ls *ls, const struct dlm_message *ms, 461962306a36Sopenharmony_ci uint32_t saved_seq) 462062306a36Sopenharmony_ci{ 462162306a36Sopenharmony_ci int error = 0, noent = 0; 462262306a36Sopenharmony_ci 462362306a36Sopenharmony_ci if (WARN_ON_ONCE(!dlm_is_member(ls, le32_to_cpu(ms->m_header.h_nodeid)))) { 462462306a36Sopenharmony_ci log_limit(ls, "receive %d from non-member %d %x %x %d", 462562306a36Sopenharmony_ci le32_to_cpu(ms->m_type), 462662306a36Sopenharmony_ci le32_to_cpu(ms->m_header.h_nodeid), 462762306a36Sopenharmony_ci le32_to_cpu(ms->m_lkid), le32_to_cpu(ms->m_remid), 462862306a36Sopenharmony_ci from_dlm_errno(le32_to_cpu(ms->m_result))); 462962306a36Sopenharmony_ci return; 463062306a36Sopenharmony_ci } 463162306a36Sopenharmony_ci 463262306a36Sopenharmony_ci switch (ms->m_type) { 463362306a36Sopenharmony_ci 463462306a36Sopenharmony_ci /* messages sent to a master node */ 463562306a36Sopenharmony_ci 463662306a36Sopenharmony_ci case cpu_to_le32(DLM_MSG_REQUEST): 463762306a36Sopenharmony_ci error = receive_request(ls, ms); 463862306a36Sopenharmony_ci break; 463962306a36Sopenharmony_ci 464062306a36Sopenharmony_ci case cpu_to_le32(DLM_MSG_CONVERT): 464162306a36Sopenharmony_ci error = receive_convert(ls, ms); 464262306a36Sopenharmony_ci break; 464362306a36Sopenharmony_ci 464462306a36Sopenharmony_ci case cpu_to_le32(DLM_MSG_UNLOCK): 464562306a36Sopenharmony_ci error = receive_unlock(ls, ms); 464662306a36Sopenharmony_ci break; 464762306a36Sopenharmony_ci 464862306a36Sopenharmony_ci case cpu_to_le32(DLM_MSG_CANCEL): 464962306a36Sopenharmony_ci noent = 1; 465062306a36Sopenharmony_ci error = receive_cancel(ls, ms); 465162306a36Sopenharmony_ci break; 465262306a36Sopenharmony_ci 465362306a36Sopenharmony_ci /* messages sent from a master node (replies to above) */ 465462306a36Sopenharmony_ci 465562306a36Sopenharmony_ci case cpu_to_le32(DLM_MSG_REQUEST_REPLY): 465662306a36Sopenharmony_ci error = receive_request_reply(ls, ms); 465762306a36Sopenharmony_ci break; 465862306a36Sopenharmony_ci 465962306a36Sopenharmony_ci case cpu_to_le32(DLM_MSG_CONVERT_REPLY): 466062306a36Sopenharmony_ci error = receive_convert_reply(ls, ms); 466162306a36Sopenharmony_ci break; 466262306a36Sopenharmony_ci 466362306a36Sopenharmony_ci case cpu_to_le32(DLM_MSG_UNLOCK_REPLY): 466462306a36Sopenharmony_ci error = receive_unlock_reply(ls, ms); 466562306a36Sopenharmony_ci break; 466662306a36Sopenharmony_ci 466762306a36Sopenharmony_ci case cpu_to_le32(DLM_MSG_CANCEL_REPLY): 466862306a36Sopenharmony_ci error = receive_cancel_reply(ls, ms); 466962306a36Sopenharmony_ci break; 467062306a36Sopenharmony_ci 467162306a36Sopenharmony_ci /* messages sent from a master node (only two types of async msg) */ 467262306a36Sopenharmony_ci 467362306a36Sopenharmony_ci case cpu_to_le32(DLM_MSG_GRANT): 467462306a36Sopenharmony_ci noent = 1; 467562306a36Sopenharmony_ci error = receive_grant(ls, ms); 467662306a36Sopenharmony_ci break; 467762306a36Sopenharmony_ci 467862306a36Sopenharmony_ci case cpu_to_le32(DLM_MSG_BAST): 467962306a36Sopenharmony_ci noent = 1; 468062306a36Sopenharmony_ci error = receive_bast(ls, ms); 468162306a36Sopenharmony_ci break; 468262306a36Sopenharmony_ci 468362306a36Sopenharmony_ci /* messages sent to a dir node */ 468462306a36Sopenharmony_ci 468562306a36Sopenharmony_ci case cpu_to_le32(DLM_MSG_LOOKUP): 468662306a36Sopenharmony_ci receive_lookup(ls, ms); 468762306a36Sopenharmony_ci break; 468862306a36Sopenharmony_ci 468962306a36Sopenharmony_ci case cpu_to_le32(DLM_MSG_REMOVE): 469062306a36Sopenharmony_ci receive_remove(ls, ms); 469162306a36Sopenharmony_ci break; 469262306a36Sopenharmony_ci 469362306a36Sopenharmony_ci /* messages sent from a dir node (remove has no reply) */ 469462306a36Sopenharmony_ci 469562306a36Sopenharmony_ci case cpu_to_le32(DLM_MSG_LOOKUP_REPLY): 469662306a36Sopenharmony_ci receive_lookup_reply(ls, ms); 469762306a36Sopenharmony_ci break; 469862306a36Sopenharmony_ci 469962306a36Sopenharmony_ci /* other messages */ 470062306a36Sopenharmony_ci 470162306a36Sopenharmony_ci case cpu_to_le32(DLM_MSG_PURGE): 470262306a36Sopenharmony_ci receive_purge(ls, ms); 470362306a36Sopenharmony_ci break; 470462306a36Sopenharmony_ci 470562306a36Sopenharmony_ci default: 470662306a36Sopenharmony_ci log_error(ls, "unknown message type %d", 470762306a36Sopenharmony_ci le32_to_cpu(ms->m_type)); 470862306a36Sopenharmony_ci } 470962306a36Sopenharmony_ci 471062306a36Sopenharmony_ci /* 471162306a36Sopenharmony_ci * When checking for ENOENT, we're checking the result of 471262306a36Sopenharmony_ci * find_lkb(m_remid): 471362306a36Sopenharmony_ci * 471462306a36Sopenharmony_ci * The lock id referenced in the message wasn't found. This may 471562306a36Sopenharmony_ci * happen in normal usage for the async messages and cancel, so 471662306a36Sopenharmony_ci * only use log_debug for them. 471762306a36Sopenharmony_ci * 471862306a36Sopenharmony_ci * Some errors are expected and normal. 471962306a36Sopenharmony_ci */ 472062306a36Sopenharmony_ci 472162306a36Sopenharmony_ci if (error == -ENOENT && noent) { 472262306a36Sopenharmony_ci log_debug(ls, "receive %d no %x remote %d %x saved_seq %u", 472362306a36Sopenharmony_ci le32_to_cpu(ms->m_type), le32_to_cpu(ms->m_remid), 472462306a36Sopenharmony_ci le32_to_cpu(ms->m_header.h_nodeid), 472562306a36Sopenharmony_ci le32_to_cpu(ms->m_lkid), saved_seq); 472662306a36Sopenharmony_ci } else if (error == -ENOENT) { 472762306a36Sopenharmony_ci log_error(ls, "receive %d no %x remote %d %x saved_seq %u", 472862306a36Sopenharmony_ci le32_to_cpu(ms->m_type), le32_to_cpu(ms->m_remid), 472962306a36Sopenharmony_ci le32_to_cpu(ms->m_header.h_nodeid), 473062306a36Sopenharmony_ci le32_to_cpu(ms->m_lkid), saved_seq); 473162306a36Sopenharmony_ci 473262306a36Sopenharmony_ci if (ms->m_type == cpu_to_le32(DLM_MSG_CONVERT)) 473362306a36Sopenharmony_ci dlm_dump_rsb_hash(ls, le32_to_cpu(ms->m_hash)); 473462306a36Sopenharmony_ci } 473562306a36Sopenharmony_ci 473662306a36Sopenharmony_ci if (error == -EINVAL) { 473762306a36Sopenharmony_ci log_error(ls, "receive %d inval from %d lkid %x remid %x " 473862306a36Sopenharmony_ci "saved_seq %u", 473962306a36Sopenharmony_ci le32_to_cpu(ms->m_type), 474062306a36Sopenharmony_ci le32_to_cpu(ms->m_header.h_nodeid), 474162306a36Sopenharmony_ci le32_to_cpu(ms->m_lkid), le32_to_cpu(ms->m_remid), 474262306a36Sopenharmony_ci saved_seq); 474362306a36Sopenharmony_ci } 474462306a36Sopenharmony_ci} 474562306a36Sopenharmony_ci 474662306a36Sopenharmony_ci/* If the lockspace is in recovery mode (locking stopped), then normal 474762306a36Sopenharmony_ci messages are saved on the requestqueue for processing after recovery is 474862306a36Sopenharmony_ci done. When not in recovery mode, we wait for dlm_recoverd to drain saved 474962306a36Sopenharmony_ci messages off the requestqueue before we process new ones. This occurs right 475062306a36Sopenharmony_ci after recovery completes when we transition from saving all messages on 475162306a36Sopenharmony_ci requestqueue, to processing all the saved messages, to processing new 475262306a36Sopenharmony_ci messages as they arrive. */ 475362306a36Sopenharmony_ci 475462306a36Sopenharmony_cistatic void dlm_receive_message(struct dlm_ls *ls, const struct dlm_message *ms, 475562306a36Sopenharmony_ci int nodeid) 475662306a36Sopenharmony_ci{ 475762306a36Sopenharmony_ci if (dlm_locking_stopped(ls)) { 475862306a36Sopenharmony_ci /* If we were a member of this lockspace, left, and rejoined, 475962306a36Sopenharmony_ci other nodes may still be sending us messages from the 476062306a36Sopenharmony_ci lockspace generation before we left. */ 476162306a36Sopenharmony_ci if (WARN_ON_ONCE(!ls->ls_generation)) { 476262306a36Sopenharmony_ci log_limit(ls, "receive %d from %d ignore old gen", 476362306a36Sopenharmony_ci le32_to_cpu(ms->m_type), nodeid); 476462306a36Sopenharmony_ci return; 476562306a36Sopenharmony_ci } 476662306a36Sopenharmony_ci 476762306a36Sopenharmony_ci dlm_add_requestqueue(ls, nodeid, ms); 476862306a36Sopenharmony_ci } else { 476962306a36Sopenharmony_ci dlm_wait_requestqueue(ls); 477062306a36Sopenharmony_ci _receive_message(ls, ms, 0); 477162306a36Sopenharmony_ci } 477262306a36Sopenharmony_ci} 477362306a36Sopenharmony_ci 477462306a36Sopenharmony_ci/* This is called by dlm_recoverd to process messages that were saved on 477562306a36Sopenharmony_ci the requestqueue. */ 477662306a36Sopenharmony_ci 477762306a36Sopenharmony_civoid dlm_receive_message_saved(struct dlm_ls *ls, const struct dlm_message *ms, 477862306a36Sopenharmony_ci uint32_t saved_seq) 477962306a36Sopenharmony_ci{ 478062306a36Sopenharmony_ci _receive_message(ls, ms, saved_seq); 478162306a36Sopenharmony_ci} 478262306a36Sopenharmony_ci 478362306a36Sopenharmony_ci/* This is called by the midcomms layer when something is received for 478462306a36Sopenharmony_ci the lockspace. It could be either a MSG (normal message sent as part of 478562306a36Sopenharmony_ci standard locking activity) or an RCOM (recovery message sent as part of 478662306a36Sopenharmony_ci lockspace recovery). */ 478762306a36Sopenharmony_ci 478862306a36Sopenharmony_civoid dlm_receive_buffer(const union dlm_packet *p, int nodeid) 478962306a36Sopenharmony_ci{ 479062306a36Sopenharmony_ci const struct dlm_header *hd = &p->header; 479162306a36Sopenharmony_ci struct dlm_ls *ls; 479262306a36Sopenharmony_ci int type = 0; 479362306a36Sopenharmony_ci 479462306a36Sopenharmony_ci switch (hd->h_cmd) { 479562306a36Sopenharmony_ci case DLM_MSG: 479662306a36Sopenharmony_ci type = le32_to_cpu(p->message.m_type); 479762306a36Sopenharmony_ci break; 479862306a36Sopenharmony_ci case DLM_RCOM: 479962306a36Sopenharmony_ci type = le32_to_cpu(p->rcom.rc_type); 480062306a36Sopenharmony_ci break; 480162306a36Sopenharmony_ci default: 480262306a36Sopenharmony_ci log_print("invalid h_cmd %d from %u", hd->h_cmd, nodeid); 480362306a36Sopenharmony_ci return; 480462306a36Sopenharmony_ci } 480562306a36Sopenharmony_ci 480662306a36Sopenharmony_ci if (le32_to_cpu(hd->h_nodeid) != nodeid) { 480762306a36Sopenharmony_ci log_print("invalid h_nodeid %d from %d lockspace %x", 480862306a36Sopenharmony_ci le32_to_cpu(hd->h_nodeid), nodeid, 480962306a36Sopenharmony_ci le32_to_cpu(hd->u.h_lockspace)); 481062306a36Sopenharmony_ci return; 481162306a36Sopenharmony_ci } 481262306a36Sopenharmony_ci 481362306a36Sopenharmony_ci ls = dlm_find_lockspace_global(le32_to_cpu(hd->u.h_lockspace)); 481462306a36Sopenharmony_ci if (!ls) { 481562306a36Sopenharmony_ci if (dlm_config.ci_log_debug) { 481662306a36Sopenharmony_ci printk_ratelimited(KERN_DEBUG "dlm: invalid lockspace " 481762306a36Sopenharmony_ci "%u from %d cmd %d type %d\n", 481862306a36Sopenharmony_ci le32_to_cpu(hd->u.h_lockspace), nodeid, 481962306a36Sopenharmony_ci hd->h_cmd, type); 482062306a36Sopenharmony_ci } 482162306a36Sopenharmony_ci 482262306a36Sopenharmony_ci if (hd->h_cmd == DLM_RCOM && type == DLM_RCOM_STATUS) 482362306a36Sopenharmony_ci dlm_send_ls_not_ready(nodeid, &p->rcom); 482462306a36Sopenharmony_ci return; 482562306a36Sopenharmony_ci } 482662306a36Sopenharmony_ci 482762306a36Sopenharmony_ci /* this rwsem allows dlm_ls_stop() to wait for all dlm_recv threads to 482862306a36Sopenharmony_ci be inactive (in this ls) before transitioning to recovery mode */ 482962306a36Sopenharmony_ci 483062306a36Sopenharmony_ci down_read(&ls->ls_recv_active); 483162306a36Sopenharmony_ci if (hd->h_cmd == DLM_MSG) 483262306a36Sopenharmony_ci dlm_receive_message(ls, &p->message, nodeid); 483362306a36Sopenharmony_ci else if (hd->h_cmd == DLM_RCOM) 483462306a36Sopenharmony_ci dlm_receive_rcom(ls, &p->rcom, nodeid); 483562306a36Sopenharmony_ci else 483662306a36Sopenharmony_ci log_error(ls, "invalid h_cmd %d from %d lockspace %x", 483762306a36Sopenharmony_ci hd->h_cmd, nodeid, le32_to_cpu(hd->u.h_lockspace)); 483862306a36Sopenharmony_ci up_read(&ls->ls_recv_active); 483962306a36Sopenharmony_ci 484062306a36Sopenharmony_ci dlm_put_lockspace(ls); 484162306a36Sopenharmony_ci} 484262306a36Sopenharmony_ci 484362306a36Sopenharmony_cistatic void recover_convert_waiter(struct dlm_ls *ls, struct dlm_lkb *lkb, 484462306a36Sopenharmony_ci struct dlm_message *ms_local) 484562306a36Sopenharmony_ci{ 484662306a36Sopenharmony_ci if (middle_conversion(lkb)) { 484762306a36Sopenharmony_ci hold_lkb(lkb); 484862306a36Sopenharmony_ci memset(ms_local, 0, sizeof(struct dlm_message)); 484962306a36Sopenharmony_ci ms_local->m_type = cpu_to_le32(DLM_MSG_CONVERT_REPLY); 485062306a36Sopenharmony_ci ms_local->m_result = cpu_to_le32(to_dlm_errno(-EINPROGRESS)); 485162306a36Sopenharmony_ci ms_local->m_header.h_nodeid = cpu_to_le32(lkb->lkb_nodeid); 485262306a36Sopenharmony_ci _receive_convert_reply(lkb, ms_local, true); 485362306a36Sopenharmony_ci 485462306a36Sopenharmony_ci /* Same special case as in receive_rcom_lock_args() */ 485562306a36Sopenharmony_ci lkb->lkb_grmode = DLM_LOCK_IV; 485662306a36Sopenharmony_ci rsb_set_flag(lkb->lkb_resource, RSB_RECOVER_CONVERT); 485762306a36Sopenharmony_ci unhold_lkb(lkb); 485862306a36Sopenharmony_ci 485962306a36Sopenharmony_ci } else if (lkb->lkb_rqmode >= lkb->lkb_grmode) { 486062306a36Sopenharmony_ci set_bit(DLM_IFL_RESEND_BIT, &lkb->lkb_iflags); 486162306a36Sopenharmony_ci } 486262306a36Sopenharmony_ci 486362306a36Sopenharmony_ci /* lkb->lkb_rqmode < lkb->lkb_grmode shouldn't happen since down 486462306a36Sopenharmony_ci conversions are async; there's no reply from the remote master */ 486562306a36Sopenharmony_ci} 486662306a36Sopenharmony_ci 486762306a36Sopenharmony_ci/* A waiting lkb needs recovery if the master node has failed, or 486862306a36Sopenharmony_ci the master node is changing (only when no directory is used) */ 486962306a36Sopenharmony_ci 487062306a36Sopenharmony_cistatic int waiter_needs_recovery(struct dlm_ls *ls, struct dlm_lkb *lkb, 487162306a36Sopenharmony_ci int dir_nodeid) 487262306a36Sopenharmony_ci{ 487362306a36Sopenharmony_ci if (dlm_no_directory(ls)) 487462306a36Sopenharmony_ci return 1; 487562306a36Sopenharmony_ci 487662306a36Sopenharmony_ci if (dlm_is_removed(ls, lkb->lkb_wait_nodeid)) 487762306a36Sopenharmony_ci return 1; 487862306a36Sopenharmony_ci 487962306a36Sopenharmony_ci return 0; 488062306a36Sopenharmony_ci} 488162306a36Sopenharmony_ci 488262306a36Sopenharmony_ci/* Recovery for locks that are waiting for replies from nodes that are now 488362306a36Sopenharmony_ci gone. We can just complete unlocks and cancels by faking a reply from the 488462306a36Sopenharmony_ci dead node. Requests and up-conversions we flag to be resent after 488562306a36Sopenharmony_ci recovery. Down-conversions can just be completed with a fake reply like 488662306a36Sopenharmony_ci unlocks. Conversions between PR and CW need special attention. */ 488762306a36Sopenharmony_ci 488862306a36Sopenharmony_civoid dlm_recover_waiters_pre(struct dlm_ls *ls) 488962306a36Sopenharmony_ci{ 489062306a36Sopenharmony_ci struct dlm_lkb *lkb, *safe; 489162306a36Sopenharmony_ci struct dlm_message *ms_local; 489262306a36Sopenharmony_ci int wait_type, local_unlock_result, local_cancel_result; 489362306a36Sopenharmony_ci int dir_nodeid; 489462306a36Sopenharmony_ci 489562306a36Sopenharmony_ci ms_local = kmalloc(sizeof(*ms_local), GFP_KERNEL); 489662306a36Sopenharmony_ci if (!ms_local) 489762306a36Sopenharmony_ci return; 489862306a36Sopenharmony_ci 489962306a36Sopenharmony_ci mutex_lock(&ls->ls_waiters_mutex); 490062306a36Sopenharmony_ci 490162306a36Sopenharmony_ci list_for_each_entry_safe(lkb, safe, &ls->ls_waiters, lkb_wait_reply) { 490262306a36Sopenharmony_ci 490362306a36Sopenharmony_ci dir_nodeid = dlm_dir_nodeid(lkb->lkb_resource); 490462306a36Sopenharmony_ci 490562306a36Sopenharmony_ci /* exclude debug messages about unlocks because there can be so 490662306a36Sopenharmony_ci many and they aren't very interesting */ 490762306a36Sopenharmony_ci 490862306a36Sopenharmony_ci if (lkb->lkb_wait_type != DLM_MSG_UNLOCK) { 490962306a36Sopenharmony_ci log_debug(ls, "waiter %x remote %x msg %d r_nodeid %d " 491062306a36Sopenharmony_ci "lkb_nodeid %d wait_nodeid %d dir_nodeid %d", 491162306a36Sopenharmony_ci lkb->lkb_id, 491262306a36Sopenharmony_ci lkb->lkb_remid, 491362306a36Sopenharmony_ci lkb->lkb_wait_type, 491462306a36Sopenharmony_ci lkb->lkb_resource->res_nodeid, 491562306a36Sopenharmony_ci lkb->lkb_nodeid, 491662306a36Sopenharmony_ci lkb->lkb_wait_nodeid, 491762306a36Sopenharmony_ci dir_nodeid); 491862306a36Sopenharmony_ci } 491962306a36Sopenharmony_ci 492062306a36Sopenharmony_ci /* all outstanding lookups, regardless of destination will be 492162306a36Sopenharmony_ci resent after recovery is done */ 492262306a36Sopenharmony_ci 492362306a36Sopenharmony_ci if (lkb->lkb_wait_type == DLM_MSG_LOOKUP) { 492462306a36Sopenharmony_ci set_bit(DLM_IFL_RESEND_BIT, &lkb->lkb_iflags); 492562306a36Sopenharmony_ci continue; 492662306a36Sopenharmony_ci } 492762306a36Sopenharmony_ci 492862306a36Sopenharmony_ci if (!waiter_needs_recovery(ls, lkb, dir_nodeid)) 492962306a36Sopenharmony_ci continue; 493062306a36Sopenharmony_ci 493162306a36Sopenharmony_ci wait_type = lkb->lkb_wait_type; 493262306a36Sopenharmony_ci local_unlock_result = -DLM_EUNLOCK; 493362306a36Sopenharmony_ci local_cancel_result = -DLM_ECANCEL; 493462306a36Sopenharmony_ci 493562306a36Sopenharmony_ci /* Main reply may have been received leaving a zero wait_type, 493662306a36Sopenharmony_ci but a reply for the overlapping op may not have been 493762306a36Sopenharmony_ci received. In that case we need to fake the appropriate 493862306a36Sopenharmony_ci reply for the overlap op. */ 493962306a36Sopenharmony_ci 494062306a36Sopenharmony_ci if (!wait_type) { 494162306a36Sopenharmony_ci if (is_overlap_cancel(lkb)) { 494262306a36Sopenharmony_ci wait_type = DLM_MSG_CANCEL; 494362306a36Sopenharmony_ci if (lkb->lkb_grmode == DLM_LOCK_IV) 494462306a36Sopenharmony_ci local_cancel_result = 0; 494562306a36Sopenharmony_ci } 494662306a36Sopenharmony_ci if (is_overlap_unlock(lkb)) { 494762306a36Sopenharmony_ci wait_type = DLM_MSG_UNLOCK; 494862306a36Sopenharmony_ci if (lkb->lkb_grmode == DLM_LOCK_IV) 494962306a36Sopenharmony_ci local_unlock_result = -ENOENT; 495062306a36Sopenharmony_ci } 495162306a36Sopenharmony_ci 495262306a36Sopenharmony_ci log_debug(ls, "rwpre overlap %x %x %d %d %d", 495362306a36Sopenharmony_ci lkb->lkb_id, dlm_iflags_val(lkb), wait_type, 495462306a36Sopenharmony_ci local_cancel_result, local_unlock_result); 495562306a36Sopenharmony_ci } 495662306a36Sopenharmony_ci 495762306a36Sopenharmony_ci switch (wait_type) { 495862306a36Sopenharmony_ci 495962306a36Sopenharmony_ci case DLM_MSG_REQUEST: 496062306a36Sopenharmony_ci set_bit(DLM_IFL_RESEND_BIT, &lkb->lkb_iflags); 496162306a36Sopenharmony_ci break; 496262306a36Sopenharmony_ci 496362306a36Sopenharmony_ci case DLM_MSG_CONVERT: 496462306a36Sopenharmony_ci recover_convert_waiter(ls, lkb, ms_local); 496562306a36Sopenharmony_ci break; 496662306a36Sopenharmony_ci 496762306a36Sopenharmony_ci case DLM_MSG_UNLOCK: 496862306a36Sopenharmony_ci hold_lkb(lkb); 496962306a36Sopenharmony_ci memset(ms_local, 0, sizeof(struct dlm_message)); 497062306a36Sopenharmony_ci ms_local->m_type = cpu_to_le32(DLM_MSG_UNLOCK_REPLY); 497162306a36Sopenharmony_ci ms_local->m_result = cpu_to_le32(to_dlm_errno(local_unlock_result)); 497262306a36Sopenharmony_ci ms_local->m_header.h_nodeid = cpu_to_le32(lkb->lkb_nodeid); 497362306a36Sopenharmony_ci _receive_unlock_reply(lkb, ms_local, true); 497462306a36Sopenharmony_ci dlm_put_lkb(lkb); 497562306a36Sopenharmony_ci break; 497662306a36Sopenharmony_ci 497762306a36Sopenharmony_ci case DLM_MSG_CANCEL: 497862306a36Sopenharmony_ci hold_lkb(lkb); 497962306a36Sopenharmony_ci memset(ms_local, 0, sizeof(struct dlm_message)); 498062306a36Sopenharmony_ci ms_local->m_type = cpu_to_le32(DLM_MSG_CANCEL_REPLY); 498162306a36Sopenharmony_ci ms_local->m_result = cpu_to_le32(to_dlm_errno(local_cancel_result)); 498262306a36Sopenharmony_ci ms_local->m_header.h_nodeid = cpu_to_le32(lkb->lkb_nodeid); 498362306a36Sopenharmony_ci _receive_cancel_reply(lkb, ms_local, true); 498462306a36Sopenharmony_ci dlm_put_lkb(lkb); 498562306a36Sopenharmony_ci break; 498662306a36Sopenharmony_ci 498762306a36Sopenharmony_ci default: 498862306a36Sopenharmony_ci log_error(ls, "invalid lkb wait_type %d %d", 498962306a36Sopenharmony_ci lkb->lkb_wait_type, wait_type); 499062306a36Sopenharmony_ci } 499162306a36Sopenharmony_ci schedule(); 499262306a36Sopenharmony_ci } 499362306a36Sopenharmony_ci mutex_unlock(&ls->ls_waiters_mutex); 499462306a36Sopenharmony_ci kfree(ms_local); 499562306a36Sopenharmony_ci} 499662306a36Sopenharmony_ci 499762306a36Sopenharmony_cistatic struct dlm_lkb *find_resend_waiter(struct dlm_ls *ls) 499862306a36Sopenharmony_ci{ 499962306a36Sopenharmony_ci struct dlm_lkb *lkb = NULL, *iter; 500062306a36Sopenharmony_ci 500162306a36Sopenharmony_ci mutex_lock(&ls->ls_waiters_mutex); 500262306a36Sopenharmony_ci list_for_each_entry(iter, &ls->ls_waiters, lkb_wait_reply) { 500362306a36Sopenharmony_ci if (test_bit(DLM_IFL_RESEND_BIT, &iter->lkb_iflags)) { 500462306a36Sopenharmony_ci hold_lkb(iter); 500562306a36Sopenharmony_ci lkb = iter; 500662306a36Sopenharmony_ci break; 500762306a36Sopenharmony_ci } 500862306a36Sopenharmony_ci } 500962306a36Sopenharmony_ci mutex_unlock(&ls->ls_waiters_mutex); 501062306a36Sopenharmony_ci 501162306a36Sopenharmony_ci return lkb; 501262306a36Sopenharmony_ci} 501362306a36Sopenharmony_ci 501462306a36Sopenharmony_ci/* Deal with lookups and lkb's marked RESEND from _pre. We may now be the 501562306a36Sopenharmony_ci master or dir-node for r. Processing the lkb may result in it being placed 501662306a36Sopenharmony_ci back on waiters. */ 501762306a36Sopenharmony_ci 501862306a36Sopenharmony_ci/* We do this after normal locking has been enabled and any saved messages 501962306a36Sopenharmony_ci (in requestqueue) have been processed. We should be confident that at 502062306a36Sopenharmony_ci this point we won't get or process a reply to any of these waiting 502162306a36Sopenharmony_ci operations. But, new ops may be coming in on the rsbs/locks here from 502262306a36Sopenharmony_ci userspace or remotely. */ 502362306a36Sopenharmony_ci 502462306a36Sopenharmony_ci/* there may have been an overlap unlock/cancel prior to recovery or after 502562306a36Sopenharmony_ci recovery. if before, the lkb may still have a pos wait_count; if after, the 502662306a36Sopenharmony_ci overlap flag would just have been set and nothing new sent. we can be 502762306a36Sopenharmony_ci confident here than any replies to either the initial op or overlap ops 502862306a36Sopenharmony_ci prior to recovery have been received. */ 502962306a36Sopenharmony_ci 503062306a36Sopenharmony_ciint dlm_recover_waiters_post(struct dlm_ls *ls) 503162306a36Sopenharmony_ci{ 503262306a36Sopenharmony_ci struct dlm_lkb *lkb; 503362306a36Sopenharmony_ci struct dlm_rsb *r; 503462306a36Sopenharmony_ci int error = 0, mstype, err, oc, ou; 503562306a36Sopenharmony_ci 503662306a36Sopenharmony_ci while (1) { 503762306a36Sopenharmony_ci if (dlm_locking_stopped(ls)) { 503862306a36Sopenharmony_ci log_debug(ls, "recover_waiters_post aborted"); 503962306a36Sopenharmony_ci error = -EINTR; 504062306a36Sopenharmony_ci break; 504162306a36Sopenharmony_ci } 504262306a36Sopenharmony_ci 504362306a36Sopenharmony_ci lkb = find_resend_waiter(ls); 504462306a36Sopenharmony_ci if (!lkb) 504562306a36Sopenharmony_ci break; 504662306a36Sopenharmony_ci 504762306a36Sopenharmony_ci r = lkb->lkb_resource; 504862306a36Sopenharmony_ci hold_rsb(r); 504962306a36Sopenharmony_ci lock_rsb(r); 505062306a36Sopenharmony_ci 505162306a36Sopenharmony_ci mstype = lkb->lkb_wait_type; 505262306a36Sopenharmony_ci oc = test_and_clear_bit(DLM_IFL_OVERLAP_CANCEL_BIT, 505362306a36Sopenharmony_ci &lkb->lkb_iflags); 505462306a36Sopenharmony_ci ou = test_and_clear_bit(DLM_IFL_OVERLAP_UNLOCK_BIT, 505562306a36Sopenharmony_ci &lkb->lkb_iflags); 505662306a36Sopenharmony_ci err = 0; 505762306a36Sopenharmony_ci 505862306a36Sopenharmony_ci log_debug(ls, "waiter %x remote %x msg %d r_nodeid %d " 505962306a36Sopenharmony_ci "lkb_nodeid %d wait_nodeid %d dir_nodeid %d " 506062306a36Sopenharmony_ci "overlap %d %d", lkb->lkb_id, lkb->lkb_remid, mstype, 506162306a36Sopenharmony_ci r->res_nodeid, lkb->lkb_nodeid, lkb->lkb_wait_nodeid, 506262306a36Sopenharmony_ci dlm_dir_nodeid(r), oc, ou); 506362306a36Sopenharmony_ci 506462306a36Sopenharmony_ci /* At this point we assume that we won't get a reply to any 506562306a36Sopenharmony_ci previous op or overlap op on this lock. First, do a big 506662306a36Sopenharmony_ci remove_from_waiters() for all previous ops. */ 506762306a36Sopenharmony_ci 506862306a36Sopenharmony_ci clear_bit(DLM_IFL_RESEND_BIT, &lkb->lkb_iflags); 506962306a36Sopenharmony_ci lkb->lkb_wait_type = 0; 507062306a36Sopenharmony_ci /* drop all wait_count references we still 507162306a36Sopenharmony_ci * hold a reference for this iteration. 507262306a36Sopenharmony_ci */ 507362306a36Sopenharmony_ci while (!atomic_dec_and_test(&lkb->lkb_wait_count)) 507462306a36Sopenharmony_ci unhold_lkb(lkb); 507562306a36Sopenharmony_ci 507662306a36Sopenharmony_ci mutex_lock(&ls->ls_waiters_mutex); 507762306a36Sopenharmony_ci list_del_init(&lkb->lkb_wait_reply); 507862306a36Sopenharmony_ci mutex_unlock(&ls->ls_waiters_mutex); 507962306a36Sopenharmony_ci 508062306a36Sopenharmony_ci if (oc || ou) { 508162306a36Sopenharmony_ci /* do an unlock or cancel instead of resending */ 508262306a36Sopenharmony_ci switch (mstype) { 508362306a36Sopenharmony_ci case DLM_MSG_LOOKUP: 508462306a36Sopenharmony_ci case DLM_MSG_REQUEST: 508562306a36Sopenharmony_ci queue_cast(r, lkb, ou ? -DLM_EUNLOCK : 508662306a36Sopenharmony_ci -DLM_ECANCEL); 508762306a36Sopenharmony_ci unhold_lkb(lkb); /* undoes create_lkb() */ 508862306a36Sopenharmony_ci break; 508962306a36Sopenharmony_ci case DLM_MSG_CONVERT: 509062306a36Sopenharmony_ci if (oc) { 509162306a36Sopenharmony_ci queue_cast(r, lkb, -DLM_ECANCEL); 509262306a36Sopenharmony_ci } else { 509362306a36Sopenharmony_ci lkb->lkb_exflags |= DLM_LKF_FORCEUNLOCK; 509462306a36Sopenharmony_ci _unlock_lock(r, lkb); 509562306a36Sopenharmony_ci } 509662306a36Sopenharmony_ci break; 509762306a36Sopenharmony_ci default: 509862306a36Sopenharmony_ci err = 1; 509962306a36Sopenharmony_ci } 510062306a36Sopenharmony_ci } else { 510162306a36Sopenharmony_ci switch (mstype) { 510262306a36Sopenharmony_ci case DLM_MSG_LOOKUP: 510362306a36Sopenharmony_ci case DLM_MSG_REQUEST: 510462306a36Sopenharmony_ci _request_lock(r, lkb); 510562306a36Sopenharmony_ci if (is_master(r)) 510662306a36Sopenharmony_ci confirm_master(r, 0); 510762306a36Sopenharmony_ci break; 510862306a36Sopenharmony_ci case DLM_MSG_CONVERT: 510962306a36Sopenharmony_ci _convert_lock(r, lkb); 511062306a36Sopenharmony_ci break; 511162306a36Sopenharmony_ci default: 511262306a36Sopenharmony_ci err = 1; 511362306a36Sopenharmony_ci } 511462306a36Sopenharmony_ci } 511562306a36Sopenharmony_ci 511662306a36Sopenharmony_ci if (err) { 511762306a36Sopenharmony_ci log_error(ls, "waiter %x msg %d r_nodeid %d " 511862306a36Sopenharmony_ci "dir_nodeid %d overlap %d %d", 511962306a36Sopenharmony_ci lkb->lkb_id, mstype, r->res_nodeid, 512062306a36Sopenharmony_ci dlm_dir_nodeid(r), oc, ou); 512162306a36Sopenharmony_ci } 512262306a36Sopenharmony_ci unlock_rsb(r); 512362306a36Sopenharmony_ci put_rsb(r); 512462306a36Sopenharmony_ci dlm_put_lkb(lkb); 512562306a36Sopenharmony_ci } 512662306a36Sopenharmony_ci 512762306a36Sopenharmony_ci return error; 512862306a36Sopenharmony_ci} 512962306a36Sopenharmony_ci 513062306a36Sopenharmony_cistatic void purge_mstcpy_list(struct dlm_ls *ls, struct dlm_rsb *r, 513162306a36Sopenharmony_ci struct list_head *list) 513262306a36Sopenharmony_ci{ 513362306a36Sopenharmony_ci struct dlm_lkb *lkb, *safe; 513462306a36Sopenharmony_ci 513562306a36Sopenharmony_ci list_for_each_entry_safe(lkb, safe, list, lkb_statequeue) { 513662306a36Sopenharmony_ci if (!is_master_copy(lkb)) 513762306a36Sopenharmony_ci continue; 513862306a36Sopenharmony_ci 513962306a36Sopenharmony_ci /* don't purge lkbs we've added in recover_master_copy for 514062306a36Sopenharmony_ci the current recovery seq */ 514162306a36Sopenharmony_ci 514262306a36Sopenharmony_ci if (lkb->lkb_recover_seq == ls->ls_recover_seq) 514362306a36Sopenharmony_ci continue; 514462306a36Sopenharmony_ci 514562306a36Sopenharmony_ci del_lkb(r, lkb); 514662306a36Sopenharmony_ci 514762306a36Sopenharmony_ci /* this put should free the lkb */ 514862306a36Sopenharmony_ci if (!dlm_put_lkb(lkb)) 514962306a36Sopenharmony_ci log_error(ls, "purged mstcpy lkb not released"); 515062306a36Sopenharmony_ci } 515162306a36Sopenharmony_ci} 515262306a36Sopenharmony_ci 515362306a36Sopenharmony_civoid dlm_purge_mstcpy_locks(struct dlm_rsb *r) 515462306a36Sopenharmony_ci{ 515562306a36Sopenharmony_ci struct dlm_ls *ls = r->res_ls; 515662306a36Sopenharmony_ci 515762306a36Sopenharmony_ci purge_mstcpy_list(ls, r, &r->res_grantqueue); 515862306a36Sopenharmony_ci purge_mstcpy_list(ls, r, &r->res_convertqueue); 515962306a36Sopenharmony_ci purge_mstcpy_list(ls, r, &r->res_waitqueue); 516062306a36Sopenharmony_ci} 516162306a36Sopenharmony_ci 516262306a36Sopenharmony_cistatic void purge_dead_list(struct dlm_ls *ls, struct dlm_rsb *r, 516362306a36Sopenharmony_ci struct list_head *list, 516462306a36Sopenharmony_ci int nodeid_gone, unsigned int *count) 516562306a36Sopenharmony_ci{ 516662306a36Sopenharmony_ci struct dlm_lkb *lkb, *safe; 516762306a36Sopenharmony_ci 516862306a36Sopenharmony_ci list_for_each_entry_safe(lkb, safe, list, lkb_statequeue) { 516962306a36Sopenharmony_ci if (!is_master_copy(lkb)) 517062306a36Sopenharmony_ci continue; 517162306a36Sopenharmony_ci 517262306a36Sopenharmony_ci if ((lkb->lkb_nodeid == nodeid_gone) || 517362306a36Sopenharmony_ci dlm_is_removed(ls, lkb->lkb_nodeid)) { 517462306a36Sopenharmony_ci 517562306a36Sopenharmony_ci /* tell recover_lvb to invalidate the lvb 517662306a36Sopenharmony_ci because a node holding EX/PW failed */ 517762306a36Sopenharmony_ci if ((lkb->lkb_exflags & DLM_LKF_VALBLK) && 517862306a36Sopenharmony_ci (lkb->lkb_grmode >= DLM_LOCK_PW)) { 517962306a36Sopenharmony_ci rsb_set_flag(r, RSB_RECOVER_LVB_INVAL); 518062306a36Sopenharmony_ci } 518162306a36Sopenharmony_ci 518262306a36Sopenharmony_ci del_lkb(r, lkb); 518362306a36Sopenharmony_ci 518462306a36Sopenharmony_ci /* this put should free the lkb */ 518562306a36Sopenharmony_ci if (!dlm_put_lkb(lkb)) 518662306a36Sopenharmony_ci log_error(ls, "purged dead lkb not released"); 518762306a36Sopenharmony_ci 518862306a36Sopenharmony_ci rsb_set_flag(r, RSB_RECOVER_GRANT); 518962306a36Sopenharmony_ci 519062306a36Sopenharmony_ci (*count)++; 519162306a36Sopenharmony_ci } 519262306a36Sopenharmony_ci } 519362306a36Sopenharmony_ci} 519462306a36Sopenharmony_ci 519562306a36Sopenharmony_ci/* Get rid of locks held by nodes that are gone. */ 519662306a36Sopenharmony_ci 519762306a36Sopenharmony_civoid dlm_recover_purge(struct dlm_ls *ls) 519862306a36Sopenharmony_ci{ 519962306a36Sopenharmony_ci struct dlm_rsb *r; 520062306a36Sopenharmony_ci struct dlm_member *memb; 520162306a36Sopenharmony_ci int nodes_count = 0; 520262306a36Sopenharmony_ci int nodeid_gone = 0; 520362306a36Sopenharmony_ci unsigned int lkb_count = 0; 520462306a36Sopenharmony_ci 520562306a36Sopenharmony_ci /* cache one removed nodeid to optimize the common 520662306a36Sopenharmony_ci case of a single node removed */ 520762306a36Sopenharmony_ci 520862306a36Sopenharmony_ci list_for_each_entry(memb, &ls->ls_nodes_gone, list) { 520962306a36Sopenharmony_ci nodes_count++; 521062306a36Sopenharmony_ci nodeid_gone = memb->nodeid; 521162306a36Sopenharmony_ci } 521262306a36Sopenharmony_ci 521362306a36Sopenharmony_ci if (!nodes_count) 521462306a36Sopenharmony_ci return; 521562306a36Sopenharmony_ci 521662306a36Sopenharmony_ci down_write(&ls->ls_root_sem); 521762306a36Sopenharmony_ci list_for_each_entry(r, &ls->ls_root_list, res_root_list) { 521862306a36Sopenharmony_ci hold_rsb(r); 521962306a36Sopenharmony_ci lock_rsb(r); 522062306a36Sopenharmony_ci if (is_master(r)) { 522162306a36Sopenharmony_ci purge_dead_list(ls, r, &r->res_grantqueue, 522262306a36Sopenharmony_ci nodeid_gone, &lkb_count); 522362306a36Sopenharmony_ci purge_dead_list(ls, r, &r->res_convertqueue, 522462306a36Sopenharmony_ci nodeid_gone, &lkb_count); 522562306a36Sopenharmony_ci purge_dead_list(ls, r, &r->res_waitqueue, 522662306a36Sopenharmony_ci nodeid_gone, &lkb_count); 522762306a36Sopenharmony_ci } 522862306a36Sopenharmony_ci unlock_rsb(r); 522962306a36Sopenharmony_ci unhold_rsb(r); 523062306a36Sopenharmony_ci cond_resched(); 523162306a36Sopenharmony_ci } 523262306a36Sopenharmony_ci up_write(&ls->ls_root_sem); 523362306a36Sopenharmony_ci 523462306a36Sopenharmony_ci if (lkb_count) 523562306a36Sopenharmony_ci log_rinfo(ls, "dlm_recover_purge %u locks for %u nodes", 523662306a36Sopenharmony_ci lkb_count, nodes_count); 523762306a36Sopenharmony_ci} 523862306a36Sopenharmony_ci 523962306a36Sopenharmony_cistatic struct dlm_rsb *find_grant_rsb(struct dlm_ls *ls, int bucket) 524062306a36Sopenharmony_ci{ 524162306a36Sopenharmony_ci struct rb_node *n; 524262306a36Sopenharmony_ci struct dlm_rsb *r; 524362306a36Sopenharmony_ci 524462306a36Sopenharmony_ci spin_lock(&ls->ls_rsbtbl[bucket].lock); 524562306a36Sopenharmony_ci for (n = rb_first(&ls->ls_rsbtbl[bucket].keep); n; n = rb_next(n)) { 524662306a36Sopenharmony_ci r = rb_entry(n, struct dlm_rsb, res_hashnode); 524762306a36Sopenharmony_ci 524862306a36Sopenharmony_ci if (!rsb_flag(r, RSB_RECOVER_GRANT)) 524962306a36Sopenharmony_ci continue; 525062306a36Sopenharmony_ci if (!is_master(r)) { 525162306a36Sopenharmony_ci rsb_clear_flag(r, RSB_RECOVER_GRANT); 525262306a36Sopenharmony_ci continue; 525362306a36Sopenharmony_ci } 525462306a36Sopenharmony_ci hold_rsb(r); 525562306a36Sopenharmony_ci spin_unlock(&ls->ls_rsbtbl[bucket].lock); 525662306a36Sopenharmony_ci return r; 525762306a36Sopenharmony_ci } 525862306a36Sopenharmony_ci spin_unlock(&ls->ls_rsbtbl[bucket].lock); 525962306a36Sopenharmony_ci return NULL; 526062306a36Sopenharmony_ci} 526162306a36Sopenharmony_ci 526262306a36Sopenharmony_ci/* 526362306a36Sopenharmony_ci * Attempt to grant locks on resources that we are the master of. 526462306a36Sopenharmony_ci * Locks may have become grantable during recovery because locks 526562306a36Sopenharmony_ci * from departed nodes have been purged (or not rebuilt), allowing 526662306a36Sopenharmony_ci * previously blocked locks to now be granted. The subset of rsb's 526762306a36Sopenharmony_ci * we are interested in are those with lkb's on either the convert or 526862306a36Sopenharmony_ci * waiting queues. 526962306a36Sopenharmony_ci * 527062306a36Sopenharmony_ci * Simplest would be to go through each master rsb and check for non-empty 527162306a36Sopenharmony_ci * convert or waiting queues, and attempt to grant on those rsbs. 527262306a36Sopenharmony_ci * Checking the queues requires lock_rsb, though, for which we'd need 527362306a36Sopenharmony_ci * to release the rsbtbl lock. This would make iterating through all 527462306a36Sopenharmony_ci * rsb's very inefficient. So, we rely on earlier recovery routines 527562306a36Sopenharmony_ci * to set RECOVER_GRANT on any rsb's that we should attempt to grant 527662306a36Sopenharmony_ci * locks for. 527762306a36Sopenharmony_ci */ 527862306a36Sopenharmony_ci 527962306a36Sopenharmony_civoid dlm_recover_grant(struct dlm_ls *ls) 528062306a36Sopenharmony_ci{ 528162306a36Sopenharmony_ci struct dlm_rsb *r; 528262306a36Sopenharmony_ci int bucket = 0; 528362306a36Sopenharmony_ci unsigned int count = 0; 528462306a36Sopenharmony_ci unsigned int rsb_count = 0; 528562306a36Sopenharmony_ci unsigned int lkb_count = 0; 528662306a36Sopenharmony_ci 528762306a36Sopenharmony_ci while (1) { 528862306a36Sopenharmony_ci r = find_grant_rsb(ls, bucket); 528962306a36Sopenharmony_ci if (!r) { 529062306a36Sopenharmony_ci if (bucket == ls->ls_rsbtbl_size - 1) 529162306a36Sopenharmony_ci break; 529262306a36Sopenharmony_ci bucket++; 529362306a36Sopenharmony_ci continue; 529462306a36Sopenharmony_ci } 529562306a36Sopenharmony_ci rsb_count++; 529662306a36Sopenharmony_ci count = 0; 529762306a36Sopenharmony_ci lock_rsb(r); 529862306a36Sopenharmony_ci /* the RECOVER_GRANT flag is checked in the grant path */ 529962306a36Sopenharmony_ci grant_pending_locks(r, &count); 530062306a36Sopenharmony_ci rsb_clear_flag(r, RSB_RECOVER_GRANT); 530162306a36Sopenharmony_ci lkb_count += count; 530262306a36Sopenharmony_ci confirm_master(r, 0); 530362306a36Sopenharmony_ci unlock_rsb(r); 530462306a36Sopenharmony_ci put_rsb(r); 530562306a36Sopenharmony_ci cond_resched(); 530662306a36Sopenharmony_ci } 530762306a36Sopenharmony_ci 530862306a36Sopenharmony_ci if (lkb_count) 530962306a36Sopenharmony_ci log_rinfo(ls, "dlm_recover_grant %u locks on %u resources", 531062306a36Sopenharmony_ci lkb_count, rsb_count); 531162306a36Sopenharmony_ci} 531262306a36Sopenharmony_ci 531362306a36Sopenharmony_cistatic struct dlm_lkb *search_remid_list(struct list_head *head, int nodeid, 531462306a36Sopenharmony_ci uint32_t remid) 531562306a36Sopenharmony_ci{ 531662306a36Sopenharmony_ci struct dlm_lkb *lkb; 531762306a36Sopenharmony_ci 531862306a36Sopenharmony_ci list_for_each_entry(lkb, head, lkb_statequeue) { 531962306a36Sopenharmony_ci if (lkb->lkb_nodeid == nodeid && lkb->lkb_remid == remid) 532062306a36Sopenharmony_ci return lkb; 532162306a36Sopenharmony_ci } 532262306a36Sopenharmony_ci return NULL; 532362306a36Sopenharmony_ci} 532462306a36Sopenharmony_ci 532562306a36Sopenharmony_cistatic struct dlm_lkb *search_remid(struct dlm_rsb *r, int nodeid, 532662306a36Sopenharmony_ci uint32_t remid) 532762306a36Sopenharmony_ci{ 532862306a36Sopenharmony_ci struct dlm_lkb *lkb; 532962306a36Sopenharmony_ci 533062306a36Sopenharmony_ci lkb = search_remid_list(&r->res_grantqueue, nodeid, remid); 533162306a36Sopenharmony_ci if (lkb) 533262306a36Sopenharmony_ci return lkb; 533362306a36Sopenharmony_ci lkb = search_remid_list(&r->res_convertqueue, nodeid, remid); 533462306a36Sopenharmony_ci if (lkb) 533562306a36Sopenharmony_ci return lkb; 533662306a36Sopenharmony_ci lkb = search_remid_list(&r->res_waitqueue, nodeid, remid); 533762306a36Sopenharmony_ci if (lkb) 533862306a36Sopenharmony_ci return lkb; 533962306a36Sopenharmony_ci return NULL; 534062306a36Sopenharmony_ci} 534162306a36Sopenharmony_ci 534262306a36Sopenharmony_ci/* needs at least dlm_rcom + rcom_lock */ 534362306a36Sopenharmony_cistatic int receive_rcom_lock_args(struct dlm_ls *ls, struct dlm_lkb *lkb, 534462306a36Sopenharmony_ci struct dlm_rsb *r, const struct dlm_rcom *rc) 534562306a36Sopenharmony_ci{ 534662306a36Sopenharmony_ci struct rcom_lock *rl = (struct rcom_lock *) rc->rc_buf; 534762306a36Sopenharmony_ci 534862306a36Sopenharmony_ci lkb->lkb_nodeid = le32_to_cpu(rc->rc_header.h_nodeid); 534962306a36Sopenharmony_ci lkb->lkb_ownpid = le32_to_cpu(rl->rl_ownpid); 535062306a36Sopenharmony_ci lkb->lkb_remid = le32_to_cpu(rl->rl_lkid); 535162306a36Sopenharmony_ci lkb->lkb_exflags = le32_to_cpu(rl->rl_exflags); 535262306a36Sopenharmony_ci dlm_set_dflags_val(lkb, le32_to_cpu(rl->rl_flags)); 535362306a36Sopenharmony_ci set_bit(DLM_IFL_MSTCPY_BIT, &lkb->lkb_iflags); 535462306a36Sopenharmony_ci lkb->lkb_lvbseq = le32_to_cpu(rl->rl_lvbseq); 535562306a36Sopenharmony_ci lkb->lkb_rqmode = rl->rl_rqmode; 535662306a36Sopenharmony_ci lkb->lkb_grmode = rl->rl_grmode; 535762306a36Sopenharmony_ci /* don't set lkb_status because add_lkb wants to itself */ 535862306a36Sopenharmony_ci 535962306a36Sopenharmony_ci lkb->lkb_bastfn = (rl->rl_asts & DLM_CB_BAST) ? &fake_bastfn : NULL; 536062306a36Sopenharmony_ci lkb->lkb_astfn = (rl->rl_asts & DLM_CB_CAST) ? &fake_astfn : NULL; 536162306a36Sopenharmony_ci 536262306a36Sopenharmony_ci if (lkb->lkb_exflags & DLM_LKF_VALBLK) { 536362306a36Sopenharmony_ci int lvblen = le16_to_cpu(rc->rc_header.h_length) - 536462306a36Sopenharmony_ci sizeof(struct dlm_rcom) - sizeof(struct rcom_lock); 536562306a36Sopenharmony_ci if (lvblen > ls->ls_lvblen) 536662306a36Sopenharmony_ci return -EINVAL; 536762306a36Sopenharmony_ci lkb->lkb_lvbptr = dlm_allocate_lvb(ls); 536862306a36Sopenharmony_ci if (!lkb->lkb_lvbptr) 536962306a36Sopenharmony_ci return -ENOMEM; 537062306a36Sopenharmony_ci memcpy(lkb->lkb_lvbptr, rl->rl_lvb, lvblen); 537162306a36Sopenharmony_ci } 537262306a36Sopenharmony_ci 537362306a36Sopenharmony_ci /* Conversions between PR and CW (middle modes) need special handling. 537462306a36Sopenharmony_ci The real granted mode of these converting locks cannot be determined 537562306a36Sopenharmony_ci until all locks have been rebuilt on the rsb (recover_conversion) */ 537662306a36Sopenharmony_ci 537762306a36Sopenharmony_ci if (rl->rl_wait_type == cpu_to_le16(DLM_MSG_CONVERT) && 537862306a36Sopenharmony_ci middle_conversion(lkb)) { 537962306a36Sopenharmony_ci rl->rl_status = DLM_LKSTS_CONVERT; 538062306a36Sopenharmony_ci lkb->lkb_grmode = DLM_LOCK_IV; 538162306a36Sopenharmony_ci rsb_set_flag(r, RSB_RECOVER_CONVERT); 538262306a36Sopenharmony_ci } 538362306a36Sopenharmony_ci 538462306a36Sopenharmony_ci return 0; 538562306a36Sopenharmony_ci} 538662306a36Sopenharmony_ci 538762306a36Sopenharmony_ci/* This lkb may have been recovered in a previous aborted recovery so we need 538862306a36Sopenharmony_ci to check if the rsb already has an lkb with the given remote nodeid/lkid. 538962306a36Sopenharmony_ci If so we just send back a standard reply. If not, we create a new lkb with 539062306a36Sopenharmony_ci the given values and send back our lkid. We send back our lkid by sending 539162306a36Sopenharmony_ci back the rcom_lock struct we got but with the remid field filled in. */ 539262306a36Sopenharmony_ci 539362306a36Sopenharmony_ci/* needs at least dlm_rcom + rcom_lock */ 539462306a36Sopenharmony_ciint dlm_recover_master_copy(struct dlm_ls *ls, const struct dlm_rcom *rc, 539562306a36Sopenharmony_ci __le32 *rl_remid, __le32 *rl_result) 539662306a36Sopenharmony_ci{ 539762306a36Sopenharmony_ci struct rcom_lock *rl = (struct rcom_lock *) rc->rc_buf; 539862306a36Sopenharmony_ci struct dlm_rsb *r; 539962306a36Sopenharmony_ci struct dlm_lkb *lkb; 540062306a36Sopenharmony_ci uint32_t remid = 0; 540162306a36Sopenharmony_ci int from_nodeid = le32_to_cpu(rc->rc_header.h_nodeid); 540262306a36Sopenharmony_ci int error; 540362306a36Sopenharmony_ci 540462306a36Sopenharmony_ci /* init rl_remid with rcom lock rl_remid */ 540562306a36Sopenharmony_ci *rl_remid = rl->rl_remid; 540662306a36Sopenharmony_ci 540762306a36Sopenharmony_ci if (rl->rl_parent_lkid) { 540862306a36Sopenharmony_ci error = -EOPNOTSUPP; 540962306a36Sopenharmony_ci goto out; 541062306a36Sopenharmony_ci } 541162306a36Sopenharmony_ci 541262306a36Sopenharmony_ci remid = le32_to_cpu(rl->rl_lkid); 541362306a36Sopenharmony_ci 541462306a36Sopenharmony_ci /* In general we expect the rsb returned to be R_MASTER, but we don't 541562306a36Sopenharmony_ci have to require it. Recovery of masters on one node can overlap 541662306a36Sopenharmony_ci recovery of locks on another node, so one node can send us MSTCPY 541762306a36Sopenharmony_ci locks before we've made ourselves master of this rsb. We can still 541862306a36Sopenharmony_ci add new MSTCPY locks that we receive here without any harm; when 541962306a36Sopenharmony_ci we make ourselves master, dlm_recover_masters() won't touch the 542062306a36Sopenharmony_ci MSTCPY locks we've received early. */ 542162306a36Sopenharmony_ci 542262306a36Sopenharmony_ci error = find_rsb(ls, rl->rl_name, le16_to_cpu(rl->rl_namelen), 542362306a36Sopenharmony_ci from_nodeid, R_RECEIVE_RECOVER, &r); 542462306a36Sopenharmony_ci if (error) 542562306a36Sopenharmony_ci goto out; 542662306a36Sopenharmony_ci 542762306a36Sopenharmony_ci lock_rsb(r); 542862306a36Sopenharmony_ci 542962306a36Sopenharmony_ci if (dlm_no_directory(ls) && (dlm_dir_nodeid(r) != dlm_our_nodeid())) { 543062306a36Sopenharmony_ci log_error(ls, "dlm_recover_master_copy remote %d %x not dir", 543162306a36Sopenharmony_ci from_nodeid, remid); 543262306a36Sopenharmony_ci error = -EBADR; 543362306a36Sopenharmony_ci goto out_unlock; 543462306a36Sopenharmony_ci } 543562306a36Sopenharmony_ci 543662306a36Sopenharmony_ci lkb = search_remid(r, from_nodeid, remid); 543762306a36Sopenharmony_ci if (lkb) { 543862306a36Sopenharmony_ci error = -EEXIST; 543962306a36Sopenharmony_ci goto out_remid; 544062306a36Sopenharmony_ci } 544162306a36Sopenharmony_ci 544262306a36Sopenharmony_ci error = create_lkb(ls, &lkb); 544362306a36Sopenharmony_ci if (error) 544462306a36Sopenharmony_ci goto out_unlock; 544562306a36Sopenharmony_ci 544662306a36Sopenharmony_ci error = receive_rcom_lock_args(ls, lkb, r, rc); 544762306a36Sopenharmony_ci if (error) { 544862306a36Sopenharmony_ci __put_lkb(ls, lkb); 544962306a36Sopenharmony_ci goto out_unlock; 545062306a36Sopenharmony_ci } 545162306a36Sopenharmony_ci 545262306a36Sopenharmony_ci attach_lkb(r, lkb); 545362306a36Sopenharmony_ci add_lkb(r, lkb, rl->rl_status); 545462306a36Sopenharmony_ci ls->ls_recover_locks_in++; 545562306a36Sopenharmony_ci 545662306a36Sopenharmony_ci if (!list_empty(&r->res_waitqueue) || !list_empty(&r->res_convertqueue)) 545762306a36Sopenharmony_ci rsb_set_flag(r, RSB_RECOVER_GRANT); 545862306a36Sopenharmony_ci 545962306a36Sopenharmony_ci out_remid: 546062306a36Sopenharmony_ci /* this is the new value returned to the lock holder for 546162306a36Sopenharmony_ci saving in its process-copy lkb */ 546262306a36Sopenharmony_ci *rl_remid = cpu_to_le32(lkb->lkb_id); 546362306a36Sopenharmony_ci 546462306a36Sopenharmony_ci lkb->lkb_recover_seq = ls->ls_recover_seq; 546562306a36Sopenharmony_ci 546662306a36Sopenharmony_ci out_unlock: 546762306a36Sopenharmony_ci unlock_rsb(r); 546862306a36Sopenharmony_ci put_rsb(r); 546962306a36Sopenharmony_ci out: 547062306a36Sopenharmony_ci if (error && error != -EEXIST) 547162306a36Sopenharmony_ci log_rinfo(ls, "dlm_recover_master_copy remote %d %x error %d", 547262306a36Sopenharmony_ci from_nodeid, remid, error); 547362306a36Sopenharmony_ci *rl_result = cpu_to_le32(error); 547462306a36Sopenharmony_ci return error; 547562306a36Sopenharmony_ci} 547662306a36Sopenharmony_ci 547762306a36Sopenharmony_ci/* needs at least dlm_rcom + rcom_lock */ 547862306a36Sopenharmony_ciint dlm_recover_process_copy(struct dlm_ls *ls, const struct dlm_rcom *rc, 547962306a36Sopenharmony_ci uint64_t seq) 548062306a36Sopenharmony_ci{ 548162306a36Sopenharmony_ci struct rcom_lock *rl = (struct rcom_lock *) rc->rc_buf; 548262306a36Sopenharmony_ci struct dlm_rsb *r; 548362306a36Sopenharmony_ci struct dlm_lkb *lkb; 548462306a36Sopenharmony_ci uint32_t lkid, remid; 548562306a36Sopenharmony_ci int error, result; 548662306a36Sopenharmony_ci 548762306a36Sopenharmony_ci lkid = le32_to_cpu(rl->rl_lkid); 548862306a36Sopenharmony_ci remid = le32_to_cpu(rl->rl_remid); 548962306a36Sopenharmony_ci result = le32_to_cpu(rl->rl_result); 549062306a36Sopenharmony_ci 549162306a36Sopenharmony_ci error = find_lkb(ls, lkid, &lkb); 549262306a36Sopenharmony_ci if (error) { 549362306a36Sopenharmony_ci log_error(ls, "dlm_recover_process_copy no %x remote %d %x %d", 549462306a36Sopenharmony_ci lkid, le32_to_cpu(rc->rc_header.h_nodeid), remid, 549562306a36Sopenharmony_ci result); 549662306a36Sopenharmony_ci return error; 549762306a36Sopenharmony_ci } 549862306a36Sopenharmony_ci 549962306a36Sopenharmony_ci r = lkb->lkb_resource; 550062306a36Sopenharmony_ci hold_rsb(r); 550162306a36Sopenharmony_ci lock_rsb(r); 550262306a36Sopenharmony_ci 550362306a36Sopenharmony_ci if (!is_process_copy(lkb)) { 550462306a36Sopenharmony_ci log_error(ls, "dlm_recover_process_copy bad %x remote %d %x %d", 550562306a36Sopenharmony_ci lkid, le32_to_cpu(rc->rc_header.h_nodeid), remid, 550662306a36Sopenharmony_ci result); 550762306a36Sopenharmony_ci dlm_dump_rsb(r); 550862306a36Sopenharmony_ci unlock_rsb(r); 550962306a36Sopenharmony_ci put_rsb(r); 551062306a36Sopenharmony_ci dlm_put_lkb(lkb); 551162306a36Sopenharmony_ci return -EINVAL; 551262306a36Sopenharmony_ci } 551362306a36Sopenharmony_ci 551462306a36Sopenharmony_ci switch (result) { 551562306a36Sopenharmony_ci case -EBADR: 551662306a36Sopenharmony_ci /* There's a chance the new master received our lock before 551762306a36Sopenharmony_ci dlm_recover_master_reply(), this wouldn't happen if we did 551862306a36Sopenharmony_ci a barrier between recover_masters and recover_locks. */ 551962306a36Sopenharmony_ci 552062306a36Sopenharmony_ci log_debug(ls, "dlm_recover_process_copy %x remote %d %x %d", 552162306a36Sopenharmony_ci lkid, le32_to_cpu(rc->rc_header.h_nodeid), remid, 552262306a36Sopenharmony_ci result); 552362306a36Sopenharmony_ci 552462306a36Sopenharmony_ci dlm_send_rcom_lock(r, lkb, seq); 552562306a36Sopenharmony_ci goto out; 552662306a36Sopenharmony_ci case -EEXIST: 552762306a36Sopenharmony_ci case 0: 552862306a36Sopenharmony_ci lkb->lkb_remid = remid; 552962306a36Sopenharmony_ci break; 553062306a36Sopenharmony_ci default: 553162306a36Sopenharmony_ci log_error(ls, "dlm_recover_process_copy %x remote %d %x %d unk", 553262306a36Sopenharmony_ci lkid, le32_to_cpu(rc->rc_header.h_nodeid), remid, 553362306a36Sopenharmony_ci result); 553462306a36Sopenharmony_ci } 553562306a36Sopenharmony_ci 553662306a36Sopenharmony_ci /* an ack for dlm_recover_locks() which waits for replies from 553762306a36Sopenharmony_ci all the locks it sends to new masters */ 553862306a36Sopenharmony_ci dlm_recovered_lock(r); 553962306a36Sopenharmony_ci out: 554062306a36Sopenharmony_ci unlock_rsb(r); 554162306a36Sopenharmony_ci put_rsb(r); 554262306a36Sopenharmony_ci dlm_put_lkb(lkb); 554362306a36Sopenharmony_ci 554462306a36Sopenharmony_ci return 0; 554562306a36Sopenharmony_ci} 554662306a36Sopenharmony_ci 554762306a36Sopenharmony_ciint dlm_user_request(struct dlm_ls *ls, struct dlm_user_args *ua, 554862306a36Sopenharmony_ci int mode, uint32_t flags, void *name, unsigned int namelen) 554962306a36Sopenharmony_ci{ 555062306a36Sopenharmony_ci struct dlm_lkb *lkb; 555162306a36Sopenharmony_ci struct dlm_args args; 555262306a36Sopenharmony_ci bool do_put = true; 555362306a36Sopenharmony_ci int error; 555462306a36Sopenharmony_ci 555562306a36Sopenharmony_ci dlm_lock_recovery(ls); 555662306a36Sopenharmony_ci 555762306a36Sopenharmony_ci error = create_lkb(ls, &lkb); 555862306a36Sopenharmony_ci if (error) { 555962306a36Sopenharmony_ci kfree(ua); 556062306a36Sopenharmony_ci goto out; 556162306a36Sopenharmony_ci } 556262306a36Sopenharmony_ci 556362306a36Sopenharmony_ci trace_dlm_lock_start(ls, lkb, name, namelen, mode, flags); 556462306a36Sopenharmony_ci 556562306a36Sopenharmony_ci if (flags & DLM_LKF_VALBLK) { 556662306a36Sopenharmony_ci ua->lksb.sb_lvbptr = kzalloc(DLM_USER_LVB_LEN, GFP_NOFS); 556762306a36Sopenharmony_ci if (!ua->lksb.sb_lvbptr) { 556862306a36Sopenharmony_ci kfree(ua); 556962306a36Sopenharmony_ci error = -ENOMEM; 557062306a36Sopenharmony_ci goto out_put; 557162306a36Sopenharmony_ci } 557262306a36Sopenharmony_ci } 557362306a36Sopenharmony_ci error = set_lock_args(mode, &ua->lksb, flags, namelen, fake_astfn, ua, 557462306a36Sopenharmony_ci fake_bastfn, &args); 557562306a36Sopenharmony_ci if (error) { 557662306a36Sopenharmony_ci kfree(ua->lksb.sb_lvbptr); 557762306a36Sopenharmony_ci ua->lksb.sb_lvbptr = NULL; 557862306a36Sopenharmony_ci kfree(ua); 557962306a36Sopenharmony_ci goto out_put; 558062306a36Sopenharmony_ci } 558162306a36Sopenharmony_ci 558262306a36Sopenharmony_ci /* After ua is attached to lkb it will be freed by dlm_free_lkb(). 558362306a36Sopenharmony_ci When DLM_DFL_USER_BIT is set, the dlm knows that this is a userspace 558462306a36Sopenharmony_ci lock and that lkb_astparam is the dlm_user_args structure. */ 558562306a36Sopenharmony_ci set_bit(DLM_DFL_USER_BIT, &lkb->lkb_dflags); 558662306a36Sopenharmony_ci error = request_lock(ls, lkb, name, namelen, &args); 558762306a36Sopenharmony_ci 558862306a36Sopenharmony_ci switch (error) { 558962306a36Sopenharmony_ci case 0: 559062306a36Sopenharmony_ci break; 559162306a36Sopenharmony_ci case -EINPROGRESS: 559262306a36Sopenharmony_ci error = 0; 559362306a36Sopenharmony_ci break; 559462306a36Sopenharmony_ci case -EAGAIN: 559562306a36Sopenharmony_ci error = 0; 559662306a36Sopenharmony_ci fallthrough; 559762306a36Sopenharmony_ci default: 559862306a36Sopenharmony_ci goto out_put; 559962306a36Sopenharmony_ci } 560062306a36Sopenharmony_ci 560162306a36Sopenharmony_ci /* add this new lkb to the per-process list of locks */ 560262306a36Sopenharmony_ci spin_lock(&ua->proc->locks_spin); 560362306a36Sopenharmony_ci hold_lkb(lkb); 560462306a36Sopenharmony_ci list_add_tail(&lkb->lkb_ownqueue, &ua->proc->locks); 560562306a36Sopenharmony_ci spin_unlock(&ua->proc->locks_spin); 560662306a36Sopenharmony_ci do_put = false; 560762306a36Sopenharmony_ci out_put: 560862306a36Sopenharmony_ci trace_dlm_lock_end(ls, lkb, name, namelen, mode, flags, error, false); 560962306a36Sopenharmony_ci if (do_put) 561062306a36Sopenharmony_ci __put_lkb(ls, lkb); 561162306a36Sopenharmony_ci out: 561262306a36Sopenharmony_ci dlm_unlock_recovery(ls); 561362306a36Sopenharmony_ci return error; 561462306a36Sopenharmony_ci} 561562306a36Sopenharmony_ci 561662306a36Sopenharmony_ciint dlm_user_convert(struct dlm_ls *ls, struct dlm_user_args *ua_tmp, 561762306a36Sopenharmony_ci int mode, uint32_t flags, uint32_t lkid, char *lvb_in) 561862306a36Sopenharmony_ci{ 561962306a36Sopenharmony_ci struct dlm_lkb *lkb; 562062306a36Sopenharmony_ci struct dlm_args args; 562162306a36Sopenharmony_ci struct dlm_user_args *ua; 562262306a36Sopenharmony_ci int error; 562362306a36Sopenharmony_ci 562462306a36Sopenharmony_ci dlm_lock_recovery(ls); 562562306a36Sopenharmony_ci 562662306a36Sopenharmony_ci error = find_lkb(ls, lkid, &lkb); 562762306a36Sopenharmony_ci if (error) 562862306a36Sopenharmony_ci goto out; 562962306a36Sopenharmony_ci 563062306a36Sopenharmony_ci trace_dlm_lock_start(ls, lkb, NULL, 0, mode, flags); 563162306a36Sopenharmony_ci 563262306a36Sopenharmony_ci /* user can change the params on its lock when it converts it, or 563362306a36Sopenharmony_ci add an lvb that didn't exist before */ 563462306a36Sopenharmony_ci 563562306a36Sopenharmony_ci ua = lkb->lkb_ua; 563662306a36Sopenharmony_ci 563762306a36Sopenharmony_ci if (flags & DLM_LKF_VALBLK && !ua->lksb.sb_lvbptr) { 563862306a36Sopenharmony_ci ua->lksb.sb_lvbptr = kzalloc(DLM_USER_LVB_LEN, GFP_NOFS); 563962306a36Sopenharmony_ci if (!ua->lksb.sb_lvbptr) { 564062306a36Sopenharmony_ci error = -ENOMEM; 564162306a36Sopenharmony_ci goto out_put; 564262306a36Sopenharmony_ci } 564362306a36Sopenharmony_ci } 564462306a36Sopenharmony_ci if (lvb_in && ua->lksb.sb_lvbptr) 564562306a36Sopenharmony_ci memcpy(ua->lksb.sb_lvbptr, lvb_in, DLM_USER_LVB_LEN); 564662306a36Sopenharmony_ci 564762306a36Sopenharmony_ci ua->xid = ua_tmp->xid; 564862306a36Sopenharmony_ci ua->castparam = ua_tmp->castparam; 564962306a36Sopenharmony_ci ua->castaddr = ua_tmp->castaddr; 565062306a36Sopenharmony_ci ua->bastparam = ua_tmp->bastparam; 565162306a36Sopenharmony_ci ua->bastaddr = ua_tmp->bastaddr; 565262306a36Sopenharmony_ci ua->user_lksb = ua_tmp->user_lksb; 565362306a36Sopenharmony_ci 565462306a36Sopenharmony_ci error = set_lock_args(mode, &ua->lksb, flags, 0, fake_astfn, ua, 565562306a36Sopenharmony_ci fake_bastfn, &args); 565662306a36Sopenharmony_ci if (error) 565762306a36Sopenharmony_ci goto out_put; 565862306a36Sopenharmony_ci 565962306a36Sopenharmony_ci error = convert_lock(ls, lkb, &args); 566062306a36Sopenharmony_ci 566162306a36Sopenharmony_ci if (error == -EINPROGRESS || error == -EAGAIN || error == -EDEADLK) 566262306a36Sopenharmony_ci error = 0; 566362306a36Sopenharmony_ci out_put: 566462306a36Sopenharmony_ci trace_dlm_lock_end(ls, lkb, NULL, 0, mode, flags, error, false); 566562306a36Sopenharmony_ci dlm_put_lkb(lkb); 566662306a36Sopenharmony_ci out: 566762306a36Sopenharmony_ci dlm_unlock_recovery(ls); 566862306a36Sopenharmony_ci kfree(ua_tmp); 566962306a36Sopenharmony_ci return error; 567062306a36Sopenharmony_ci} 567162306a36Sopenharmony_ci 567262306a36Sopenharmony_ci/* 567362306a36Sopenharmony_ci * The caller asks for an orphan lock on a given resource with a given mode. 567462306a36Sopenharmony_ci * If a matching lock exists, it's moved to the owner's list of locks and 567562306a36Sopenharmony_ci * the lkid is returned. 567662306a36Sopenharmony_ci */ 567762306a36Sopenharmony_ci 567862306a36Sopenharmony_ciint dlm_user_adopt_orphan(struct dlm_ls *ls, struct dlm_user_args *ua_tmp, 567962306a36Sopenharmony_ci int mode, uint32_t flags, void *name, unsigned int namelen, 568062306a36Sopenharmony_ci uint32_t *lkid) 568162306a36Sopenharmony_ci{ 568262306a36Sopenharmony_ci struct dlm_lkb *lkb = NULL, *iter; 568362306a36Sopenharmony_ci struct dlm_user_args *ua; 568462306a36Sopenharmony_ci int found_other_mode = 0; 568562306a36Sopenharmony_ci int rv = 0; 568662306a36Sopenharmony_ci 568762306a36Sopenharmony_ci mutex_lock(&ls->ls_orphans_mutex); 568862306a36Sopenharmony_ci list_for_each_entry(iter, &ls->ls_orphans, lkb_ownqueue) { 568962306a36Sopenharmony_ci if (iter->lkb_resource->res_length != namelen) 569062306a36Sopenharmony_ci continue; 569162306a36Sopenharmony_ci if (memcmp(iter->lkb_resource->res_name, name, namelen)) 569262306a36Sopenharmony_ci continue; 569362306a36Sopenharmony_ci if (iter->lkb_grmode != mode) { 569462306a36Sopenharmony_ci found_other_mode = 1; 569562306a36Sopenharmony_ci continue; 569662306a36Sopenharmony_ci } 569762306a36Sopenharmony_ci 569862306a36Sopenharmony_ci lkb = iter; 569962306a36Sopenharmony_ci list_del_init(&iter->lkb_ownqueue); 570062306a36Sopenharmony_ci clear_bit(DLM_DFL_ORPHAN_BIT, &iter->lkb_dflags); 570162306a36Sopenharmony_ci *lkid = iter->lkb_id; 570262306a36Sopenharmony_ci break; 570362306a36Sopenharmony_ci } 570462306a36Sopenharmony_ci mutex_unlock(&ls->ls_orphans_mutex); 570562306a36Sopenharmony_ci 570662306a36Sopenharmony_ci if (!lkb && found_other_mode) { 570762306a36Sopenharmony_ci rv = -EAGAIN; 570862306a36Sopenharmony_ci goto out; 570962306a36Sopenharmony_ci } 571062306a36Sopenharmony_ci 571162306a36Sopenharmony_ci if (!lkb) { 571262306a36Sopenharmony_ci rv = -ENOENT; 571362306a36Sopenharmony_ci goto out; 571462306a36Sopenharmony_ci } 571562306a36Sopenharmony_ci 571662306a36Sopenharmony_ci lkb->lkb_exflags = flags; 571762306a36Sopenharmony_ci lkb->lkb_ownpid = (int) current->pid; 571862306a36Sopenharmony_ci 571962306a36Sopenharmony_ci ua = lkb->lkb_ua; 572062306a36Sopenharmony_ci 572162306a36Sopenharmony_ci ua->proc = ua_tmp->proc; 572262306a36Sopenharmony_ci ua->xid = ua_tmp->xid; 572362306a36Sopenharmony_ci ua->castparam = ua_tmp->castparam; 572462306a36Sopenharmony_ci ua->castaddr = ua_tmp->castaddr; 572562306a36Sopenharmony_ci ua->bastparam = ua_tmp->bastparam; 572662306a36Sopenharmony_ci ua->bastaddr = ua_tmp->bastaddr; 572762306a36Sopenharmony_ci ua->user_lksb = ua_tmp->user_lksb; 572862306a36Sopenharmony_ci 572962306a36Sopenharmony_ci /* 573062306a36Sopenharmony_ci * The lkb reference from the ls_orphans list was not 573162306a36Sopenharmony_ci * removed above, and is now considered the reference 573262306a36Sopenharmony_ci * for the proc locks list. 573362306a36Sopenharmony_ci */ 573462306a36Sopenharmony_ci 573562306a36Sopenharmony_ci spin_lock(&ua->proc->locks_spin); 573662306a36Sopenharmony_ci list_add_tail(&lkb->lkb_ownqueue, &ua->proc->locks); 573762306a36Sopenharmony_ci spin_unlock(&ua->proc->locks_spin); 573862306a36Sopenharmony_ci out: 573962306a36Sopenharmony_ci kfree(ua_tmp); 574062306a36Sopenharmony_ci return rv; 574162306a36Sopenharmony_ci} 574262306a36Sopenharmony_ci 574362306a36Sopenharmony_ciint dlm_user_unlock(struct dlm_ls *ls, struct dlm_user_args *ua_tmp, 574462306a36Sopenharmony_ci uint32_t flags, uint32_t lkid, char *lvb_in) 574562306a36Sopenharmony_ci{ 574662306a36Sopenharmony_ci struct dlm_lkb *lkb; 574762306a36Sopenharmony_ci struct dlm_args args; 574862306a36Sopenharmony_ci struct dlm_user_args *ua; 574962306a36Sopenharmony_ci int error; 575062306a36Sopenharmony_ci 575162306a36Sopenharmony_ci dlm_lock_recovery(ls); 575262306a36Sopenharmony_ci 575362306a36Sopenharmony_ci error = find_lkb(ls, lkid, &lkb); 575462306a36Sopenharmony_ci if (error) 575562306a36Sopenharmony_ci goto out; 575662306a36Sopenharmony_ci 575762306a36Sopenharmony_ci trace_dlm_unlock_start(ls, lkb, flags); 575862306a36Sopenharmony_ci 575962306a36Sopenharmony_ci ua = lkb->lkb_ua; 576062306a36Sopenharmony_ci 576162306a36Sopenharmony_ci if (lvb_in && ua->lksb.sb_lvbptr) 576262306a36Sopenharmony_ci memcpy(ua->lksb.sb_lvbptr, lvb_in, DLM_USER_LVB_LEN); 576362306a36Sopenharmony_ci if (ua_tmp->castparam) 576462306a36Sopenharmony_ci ua->castparam = ua_tmp->castparam; 576562306a36Sopenharmony_ci ua->user_lksb = ua_tmp->user_lksb; 576662306a36Sopenharmony_ci 576762306a36Sopenharmony_ci error = set_unlock_args(flags, ua, &args); 576862306a36Sopenharmony_ci if (error) 576962306a36Sopenharmony_ci goto out_put; 577062306a36Sopenharmony_ci 577162306a36Sopenharmony_ci error = unlock_lock(ls, lkb, &args); 577262306a36Sopenharmony_ci 577362306a36Sopenharmony_ci if (error == -DLM_EUNLOCK) 577462306a36Sopenharmony_ci error = 0; 577562306a36Sopenharmony_ci /* from validate_unlock_args() */ 577662306a36Sopenharmony_ci if (error == -EBUSY && (flags & DLM_LKF_FORCEUNLOCK)) 577762306a36Sopenharmony_ci error = 0; 577862306a36Sopenharmony_ci if (error) 577962306a36Sopenharmony_ci goto out_put; 578062306a36Sopenharmony_ci 578162306a36Sopenharmony_ci spin_lock(&ua->proc->locks_spin); 578262306a36Sopenharmony_ci /* dlm_user_add_cb() may have already taken lkb off the proc list */ 578362306a36Sopenharmony_ci if (!list_empty(&lkb->lkb_ownqueue)) 578462306a36Sopenharmony_ci list_move(&lkb->lkb_ownqueue, &ua->proc->unlocking); 578562306a36Sopenharmony_ci spin_unlock(&ua->proc->locks_spin); 578662306a36Sopenharmony_ci out_put: 578762306a36Sopenharmony_ci trace_dlm_unlock_end(ls, lkb, flags, error); 578862306a36Sopenharmony_ci dlm_put_lkb(lkb); 578962306a36Sopenharmony_ci out: 579062306a36Sopenharmony_ci dlm_unlock_recovery(ls); 579162306a36Sopenharmony_ci kfree(ua_tmp); 579262306a36Sopenharmony_ci return error; 579362306a36Sopenharmony_ci} 579462306a36Sopenharmony_ci 579562306a36Sopenharmony_ciint dlm_user_cancel(struct dlm_ls *ls, struct dlm_user_args *ua_tmp, 579662306a36Sopenharmony_ci uint32_t flags, uint32_t lkid) 579762306a36Sopenharmony_ci{ 579862306a36Sopenharmony_ci struct dlm_lkb *lkb; 579962306a36Sopenharmony_ci struct dlm_args args; 580062306a36Sopenharmony_ci struct dlm_user_args *ua; 580162306a36Sopenharmony_ci int error; 580262306a36Sopenharmony_ci 580362306a36Sopenharmony_ci dlm_lock_recovery(ls); 580462306a36Sopenharmony_ci 580562306a36Sopenharmony_ci error = find_lkb(ls, lkid, &lkb); 580662306a36Sopenharmony_ci if (error) 580762306a36Sopenharmony_ci goto out; 580862306a36Sopenharmony_ci 580962306a36Sopenharmony_ci trace_dlm_unlock_start(ls, lkb, flags); 581062306a36Sopenharmony_ci 581162306a36Sopenharmony_ci ua = lkb->lkb_ua; 581262306a36Sopenharmony_ci if (ua_tmp->castparam) 581362306a36Sopenharmony_ci ua->castparam = ua_tmp->castparam; 581462306a36Sopenharmony_ci ua->user_lksb = ua_tmp->user_lksb; 581562306a36Sopenharmony_ci 581662306a36Sopenharmony_ci error = set_unlock_args(flags, ua, &args); 581762306a36Sopenharmony_ci if (error) 581862306a36Sopenharmony_ci goto out_put; 581962306a36Sopenharmony_ci 582062306a36Sopenharmony_ci error = cancel_lock(ls, lkb, &args); 582162306a36Sopenharmony_ci 582262306a36Sopenharmony_ci if (error == -DLM_ECANCEL) 582362306a36Sopenharmony_ci error = 0; 582462306a36Sopenharmony_ci /* from validate_unlock_args() */ 582562306a36Sopenharmony_ci if (error == -EBUSY) 582662306a36Sopenharmony_ci error = 0; 582762306a36Sopenharmony_ci out_put: 582862306a36Sopenharmony_ci trace_dlm_unlock_end(ls, lkb, flags, error); 582962306a36Sopenharmony_ci dlm_put_lkb(lkb); 583062306a36Sopenharmony_ci out: 583162306a36Sopenharmony_ci dlm_unlock_recovery(ls); 583262306a36Sopenharmony_ci kfree(ua_tmp); 583362306a36Sopenharmony_ci return error; 583462306a36Sopenharmony_ci} 583562306a36Sopenharmony_ci 583662306a36Sopenharmony_ciint dlm_user_deadlock(struct dlm_ls *ls, uint32_t flags, uint32_t lkid) 583762306a36Sopenharmony_ci{ 583862306a36Sopenharmony_ci struct dlm_lkb *lkb; 583962306a36Sopenharmony_ci struct dlm_args args; 584062306a36Sopenharmony_ci struct dlm_user_args *ua; 584162306a36Sopenharmony_ci struct dlm_rsb *r; 584262306a36Sopenharmony_ci int error; 584362306a36Sopenharmony_ci 584462306a36Sopenharmony_ci dlm_lock_recovery(ls); 584562306a36Sopenharmony_ci 584662306a36Sopenharmony_ci error = find_lkb(ls, lkid, &lkb); 584762306a36Sopenharmony_ci if (error) 584862306a36Sopenharmony_ci goto out; 584962306a36Sopenharmony_ci 585062306a36Sopenharmony_ci trace_dlm_unlock_start(ls, lkb, flags); 585162306a36Sopenharmony_ci 585262306a36Sopenharmony_ci ua = lkb->lkb_ua; 585362306a36Sopenharmony_ci 585462306a36Sopenharmony_ci error = set_unlock_args(flags, ua, &args); 585562306a36Sopenharmony_ci if (error) 585662306a36Sopenharmony_ci goto out_put; 585762306a36Sopenharmony_ci 585862306a36Sopenharmony_ci /* same as cancel_lock(), but set DEADLOCK_CANCEL after lock_rsb */ 585962306a36Sopenharmony_ci 586062306a36Sopenharmony_ci r = lkb->lkb_resource; 586162306a36Sopenharmony_ci hold_rsb(r); 586262306a36Sopenharmony_ci lock_rsb(r); 586362306a36Sopenharmony_ci 586462306a36Sopenharmony_ci error = validate_unlock_args(lkb, &args); 586562306a36Sopenharmony_ci if (error) 586662306a36Sopenharmony_ci goto out_r; 586762306a36Sopenharmony_ci set_bit(DLM_IFL_DEADLOCK_CANCEL_BIT, &lkb->lkb_iflags); 586862306a36Sopenharmony_ci 586962306a36Sopenharmony_ci error = _cancel_lock(r, lkb); 587062306a36Sopenharmony_ci out_r: 587162306a36Sopenharmony_ci unlock_rsb(r); 587262306a36Sopenharmony_ci put_rsb(r); 587362306a36Sopenharmony_ci 587462306a36Sopenharmony_ci if (error == -DLM_ECANCEL) 587562306a36Sopenharmony_ci error = 0; 587662306a36Sopenharmony_ci /* from validate_unlock_args() */ 587762306a36Sopenharmony_ci if (error == -EBUSY) 587862306a36Sopenharmony_ci error = 0; 587962306a36Sopenharmony_ci out_put: 588062306a36Sopenharmony_ci trace_dlm_unlock_end(ls, lkb, flags, error); 588162306a36Sopenharmony_ci dlm_put_lkb(lkb); 588262306a36Sopenharmony_ci out: 588362306a36Sopenharmony_ci dlm_unlock_recovery(ls); 588462306a36Sopenharmony_ci return error; 588562306a36Sopenharmony_ci} 588662306a36Sopenharmony_ci 588762306a36Sopenharmony_ci/* lkb's that are removed from the waiters list by revert are just left on the 588862306a36Sopenharmony_ci orphans list with the granted orphan locks, to be freed by purge */ 588962306a36Sopenharmony_ci 589062306a36Sopenharmony_cistatic int orphan_proc_lock(struct dlm_ls *ls, struct dlm_lkb *lkb) 589162306a36Sopenharmony_ci{ 589262306a36Sopenharmony_ci struct dlm_args args; 589362306a36Sopenharmony_ci int error; 589462306a36Sopenharmony_ci 589562306a36Sopenharmony_ci hold_lkb(lkb); /* reference for the ls_orphans list */ 589662306a36Sopenharmony_ci mutex_lock(&ls->ls_orphans_mutex); 589762306a36Sopenharmony_ci list_add_tail(&lkb->lkb_ownqueue, &ls->ls_orphans); 589862306a36Sopenharmony_ci mutex_unlock(&ls->ls_orphans_mutex); 589962306a36Sopenharmony_ci 590062306a36Sopenharmony_ci set_unlock_args(0, lkb->lkb_ua, &args); 590162306a36Sopenharmony_ci 590262306a36Sopenharmony_ci error = cancel_lock(ls, lkb, &args); 590362306a36Sopenharmony_ci if (error == -DLM_ECANCEL) 590462306a36Sopenharmony_ci error = 0; 590562306a36Sopenharmony_ci return error; 590662306a36Sopenharmony_ci} 590762306a36Sopenharmony_ci 590862306a36Sopenharmony_ci/* The FORCEUNLOCK flag allows the unlock to go ahead even if the lkb isn't 590962306a36Sopenharmony_ci granted. Regardless of what rsb queue the lock is on, it's removed and 591062306a36Sopenharmony_ci freed. The IVVALBLK flag causes the lvb on the resource to be invalidated 591162306a36Sopenharmony_ci if our lock is PW/EX (it's ignored if our granted mode is smaller.) */ 591262306a36Sopenharmony_ci 591362306a36Sopenharmony_cistatic int unlock_proc_lock(struct dlm_ls *ls, struct dlm_lkb *lkb) 591462306a36Sopenharmony_ci{ 591562306a36Sopenharmony_ci struct dlm_args args; 591662306a36Sopenharmony_ci int error; 591762306a36Sopenharmony_ci 591862306a36Sopenharmony_ci set_unlock_args(DLM_LKF_FORCEUNLOCK | DLM_LKF_IVVALBLK, 591962306a36Sopenharmony_ci lkb->lkb_ua, &args); 592062306a36Sopenharmony_ci 592162306a36Sopenharmony_ci error = unlock_lock(ls, lkb, &args); 592262306a36Sopenharmony_ci if (error == -DLM_EUNLOCK) 592362306a36Sopenharmony_ci error = 0; 592462306a36Sopenharmony_ci return error; 592562306a36Sopenharmony_ci} 592662306a36Sopenharmony_ci 592762306a36Sopenharmony_ci/* We have to release clear_proc_locks mutex before calling unlock_proc_lock() 592862306a36Sopenharmony_ci (which does lock_rsb) due to deadlock with receiving a message that does 592962306a36Sopenharmony_ci lock_rsb followed by dlm_user_add_cb() */ 593062306a36Sopenharmony_ci 593162306a36Sopenharmony_cistatic struct dlm_lkb *del_proc_lock(struct dlm_ls *ls, 593262306a36Sopenharmony_ci struct dlm_user_proc *proc) 593362306a36Sopenharmony_ci{ 593462306a36Sopenharmony_ci struct dlm_lkb *lkb = NULL; 593562306a36Sopenharmony_ci 593662306a36Sopenharmony_ci spin_lock(&ls->ls_clear_proc_locks); 593762306a36Sopenharmony_ci if (list_empty(&proc->locks)) 593862306a36Sopenharmony_ci goto out; 593962306a36Sopenharmony_ci 594062306a36Sopenharmony_ci lkb = list_entry(proc->locks.next, struct dlm_lkb, lkb_ownqueue); 594162306a36Sopenharmony_ci list_del_init(&lkb->lkb_ownqueue); 594262306a36Sopenharmony_ci 594362306a36Sopenharmony_ci if (lkb->lkb_exflags & DLM_LKF_PERSISTENT) 594462306a36Sopenharmony_ci set_bit(DLM_DFL_ORPHAN_BIT, &lkb->lkb_dflags); 594562306a36Sopenharmony_ci else 594662306a36Sopenharmony_ci set_bit(DLM_IFL_DEAD_BIT, &lkb->lkb_iflags); 594762306a36Sopenharmony_ci out: 594862306a36Sopenharmony_ci spin_unlock(&ls->ls_clear_proc_locks); 594962306a36Sopenharmony_ci return lkb; 595062306a36Sopenharmony_ci} 595162306a36Sopenharmony_ci 595262306a36Sopenharmony_ci/* The ls_clear_proc_locks mutex protects against dlm_user_add_cb() which 595362306a36Sopenharmony_ci 1) references lkb->ua which we free here and 2) adds lkbs to proc->asts, 595462306a36Sopenharmony_ci which we clear here. */ 595562306a36Sopenharmony_ci 595662306a36Sopenharmony_ci/* proc CLOSING flag is set so no more device_reads should look at proc->asts 595762306a36Sopenharmony_ci list, and no more device_writes should add lkb's to proc->locks list; so we 595862306a36Sopenharmony_ci shouldn't need to take asts_spin or locks_spin here. this assumes that 595962306a36Sopenharmony_ci device reads/writes/closes are serialized -- FIXME: we may need to serialize 596062306a36Sopenharmony_ci them ourself. */ 596162306a36Sopenharmony_ci 596262306a36Sopenharmony_civoid dlm_clear_proc_locks(struct dlm_ls *ls, struct dlm_user_proc *proc) 596362306a36Sopenharmony_ci{ 596462306a36Sopenharmony_ci struct dlm_lkb *lkb, *safe; 596562306a36Sopenharmony_ci 596662306a36Sopenharmony_ci dlm_lock_recovery(ls); 596762306a36Sopenharmony_ci 596862306a36Sopenharmony_ci while (1) { 596962306a36Sopenharmony_ci lkb = del_proc_lock(ls, proc); 597062306a36Sopenharmony_ci if (!lkb) 597162306a36Sopenharmony_ci break; 597262306a36Sopenharmony_ci if (lkb->lkb_exflags & DLM_LKF_PERSISTENT) 597362306a36Sopenharmony_ci orphan_proc_lock(ls, lkb); 597462306a36Sopenharmony_ci else 597562306a36Sopenharmony_ci unlock_proc_lock(ls, lkb); 597662306a36Sopenharmony_ci 597762306a36Sopenharmony_ci /* this removes the reference for the proc->locks list 597862306a36Sopenharmony_ci added by dlm_user_request, it may result in the lkb 597962306a36Sopenharmony_ci being freed */ 598062306a36Sopenharmony_ci 598162306a36Sopenharmony_ci dlm_put_lkb(lkb); 598262306a36Sopenharmony_ci } 598362306a36Sopenharmony_ci 598462306a36Sopenharmony_ci spin_lock(&ls->ls_clear_proc_locks); 598562306a36Sopenharmony_ci 598662306a36Sopenharmony_ci /* in-progress unlocks */ 598762306a36Sopenharmony_ci list_for_each_entry_safe(lkb, safe, &proc->unlocking, lkb_ownqueue) { 598862306a36Sopenharmony_ci list_del_init(&lkb->lkb_ownqueue); 598962306a36Sopenharmony_ci set_bit(DLM_IFL_DEAD_BIT, &lkb->lkb_iflags); 599062306a36Sopenharmony_ci dlm_put_lkb(lkb); 599162306a36Sopenharmony_ci } 599262306a36Sopenharmony_ci 599362306a36Sopenharmony_ci list_for_each_entry_safe(lkb, safe, &proc->asts, lkb_cb_list) { 599462306a36Sopenharmony_ci dlm_purge_lkb_callbacks(lkb); 599562306a36Sopenharmony_ci list_del_init(&lkb->lkb_cb_list); 599662306a36Sopenharmony_ci dlm_put_lkb(lkb); 599762306a36Sopenharmony_ci } 599862306a36Sopenharmony_ci 599962306a36Sopenharmony_ci spin_unlock(&ls->ls_clear_proc_locks); 600062306a36Sopenharmony_ci dlm_unlock_recovery(ls); 600162306a36Sopenharmony_ci} 600262306a36Sopenharmony_ci 600362306a36Sopenharmony_cistatic void purge_proc_locks(struct dlm_ls *ls, struct dlm_user_proc *proc) 600462306a36Sopenharmony_ci{ 600562306a36Sopenharmony_ci struct dlm_lkb *lkb, *safe; 600662306a36Sopenharmony_ci 600762306a36Sopenharmony_ci while (1) { 600862306a36Sopenharmony_ci lkb = NULL; 600962306a36Sopenharmony_ci spin_lock(&proc->locks_spin); 601062306a36Sopenharmony_ci if (!list_empty(&proc->locks)) { 601162306a36Sopenharmony_ci lkb = list_entry(proc->locks.next, struct dlm_lkb, 601262306a36Sopenharmony_ci lkb_ownqueue); 601362306a36Sopenharmony_ci list_del_init(&lkb->lkb_ownqueue); 601462306a36Sopenharmony_ci } 601562306a36Sopenharmony_ci spin_unlock(&proc->locks_spin); 601662306a36Sopenharmony_ci 601762306a36Sopenharmony_ci if (!lkb) 601862306a36Sopenharmony_ci break; 601962306a36Sopenharmony_ci 602062306a36Sopenharmony_ci set_bit(DLM_IFL_DEAD_BIT, &lkb->lkb_iflags); 602162306a36Sopenharmony_ci unlock_proc_lock(ls, lkb); 602262306a36Sopenharmony_ci dlm_put_lkb(lkb); /* ref from proc->locks list */ 602362306a36Sopenharmony_ci } 602462306a36Sopenharmony_ci 602562306a36Sopenharmony_ci spin_lock(&proc->locks_spin); 602662306a36Sopenharmony_ci list_for_each_entry_safe(lkb, safe, &proc->unlocking, lkb_ownqueue) { 602762306a36Sopenharmony_ci list_del_init(&lkb->lkb_ownqueue); 602862306a36Sopenharmony_ci set_bit(DLM_IFL_DEAD_BIT, &lkb->lkb_iflags); 602962306a36Sopenharmony_ci dlm_put_lkb(lkb); 603062306a36Sopenharmony_ci } 603162306a36Sopenharmony_ci spin_unlock(&proc->locks_spin); 603262306a36Sopenharmony_ci 603362306a36Sopenharmony_ci spin_lock(&proc->asts_spin); 603462306a36Sopenharmony_ci list_for_each_entry_safe(lkb, safe, &proc->asts, lkb_cb_list) { 603562306a36Sopenharmony_ci dlm_purge_lkb_callbacks(lkb); 603662306a36Sopenharmony_ci list_del_init(&lkb->lkb_cb_list); 603762306a36Sopenharmony_ci dlm_put_lkb(lkb); 603862306a36Sopenharmony_ci } 603962306a36Sopenharmony_ci spin_unlock(&proc->asts_spin); 604062306a36Sopenharmony_ci} 604162306a36Sopenharmony_ci 604262306a36Sopenharmony_ci/* pid of 0 means purge all orphans */ 604362306a36Sopenharmony_ci 604462306a36Sopenharmony_cistatic void do_purge(struct dlm_ls *ls, int nodeid, int pid) 604562306a36Sopenharmony_ci{ 604662306a36Sopenharmony_ci struct dlm_lkb *lkb, *safe; 604762306a36Sopenharmony_ci 604862306a36Sopenharmony_ci mutex_lock(&ls->ls_orphans_mutex); 604962306a36Sopenharmony_ci list_for_each_entry_safe(lkb, safe, &ls->ls_orphans, lkb_ownqueue) { 605062306a36Sopenharmony_ci if (pid && lkb->lkb_ownpid != pid) 605162306a36Sopenharmony_ci continue; 605262306a36Sopenharmony_ci unlock_proc_lock(ls, lkb); 605362306a36Sopenharmony_ci list_del_init(&lkb->lkb_ownqueue); 605462306a36Sopenharmony_ci dlm_put_lkb(lkb); 605562306a36Sopenharmony_ci } 605662306a36Sopenharmony_ci mutex_unlock(&ls->ls_orphans_mutex); 605762306a36Sopenharmony_ci} 605862306a36Sopenharmony_ci 605962306a36Sopenharmony_cistatic int send_purge(struct dlm_ls *ls, int nodeid, int pid) 606062306a36Sopenharmony_ci{ 606162306a36Sopenharmony_ci struct dlm_message *ms; 606262306a36Sopenharmony_ci struct dlm_mhandle *mh; 606362306a36Sopenharmony_ci int error; 606462306a36Sopenharmony_ci 606562306a36Sopenharmony_ci error = _create_message(ls, sizeof(struct dlm_message), nodeid, 606662306a36Sopenharmony_ci DLM_MSG_PURGE, &ms, &mh, GFP_NOFS); 606762306a36Sopenharmony_ci if (error) 606862306a36Sopenharmony_ci return error; 606962306a36Sopenharmony_ci ms->m_nodeid = cpu_to_le32(nodeid); 607062306a36Sopenharmony_ci ms->m_pid = cpu_to_le32(pid); 607162306a36Sopenharmony_ci 607262306a36Sopenharmony_ci return send_message(mh, ms, NULL, 0); 607362306a36Sopenharmony_ci} 607462306a36Sopenharmony_ci 607562306a36Sopenharmony_ciint dlm_user_purge(struct dlm_ls *ls, struct dlm_user_proc *proc, 607662306a36Sopenharmony_ci int nodeid, int pid) 607762306a36Sopenharmony_ci{ 607862306a36Sopenharmony_ci int error = 0; 607962306a36Sopenharmony_ci 608062306a36Sopenharmony_ci if (nodeid && (nodeid != dlm_our_nodeid())) { 608162306a36Sopenharmony_ci error = send_purge(ls, nodeid, pid); 608262306a36Sopenharmony_ci } else { 608362306a36Sopenharmony_ci dlm_lock_recovery(ls); 608462306a36Sopenharmony_ci if (pid == current->pid) 608562306a36Sopenharmony_ci purge_proc_locks(ls, proc); 608662306a36Sopenharmony_ci else 608762306a36Sopenharmony_ci do_purge(ls, nodeid, pid); 608862306a36Sopenharmony_ci dlm_unlock_recovery(ls); 608962306a36Sopenharmony_ci } 609062306a36Sopenharmony_ci return error; 609162306a36Sopenharmony_ci} 609262306a36Sopenharmony_ci 609362306a36Sopenharmony_ci/* debug functionality */ 609462306a36Sopenharmony_ciint dlm_debug_add_lkb(struct dlm_ls *ls, uint32_t lkb_id, char *name, int len, 609562306a36Sopenharmony_ci int lkb_nodeid, unsigned int lkb_dflags, int lkb_status) 609662306a36Sopenharmony_ci{ 609762306a36Sopenharmony_ci struct dlm_lksb *lksb; 609862306a36Sopenharmony_ci struct dlm_lkb *lkb; 609962306a36Sopenharmony_ci struct dlm_rsb *r; 610062306a36Sopenharmony_ci int error; 610162306a36Sopenharmony_ci 610262306a36Sopenharmony_ci /* we currently can't set a valid user lock */ 610362306a36Sopenharmony_ci if (lkb_dflags & BIT(DLM_DFL_USER_BIT)) 610462306a36Sopenharmony_ci return -EOPNOTSUPP; 610562306a36Sopenharmony_ci 610662306a36Sopenharmony_ci lksb = kzalloc(sizeof(*lksb), GFP_NOFS); 610762306a36Sopenharmony_ci if (!lksb) 610862306a36Sopenharmony_ci return -ENOMEM; 610962306a36Sopenharmony_ci 611062306a36Sopenharmony_ci error = _create_lkb(ls, &lkb, lkb_id, lkb_id + 1); 611162306a36Sopenharmony_ci if (error) { 611262306a36Sopenharmony_ci kfree(lksb); 611362306a36Sopenharmony_ci return error; 611462306a36Sopenharmony_ci } 611562306a36Sopenharmony_ci 611662306a36Sopenharmony_ci dlm_set_dflags_val(lkb, lkb_dflags); 611762306a36Sopenharmony_ci lkb->lkb_nodeid = lkb_nodeid; 611862306a36Sopenharmony_ci lkb->lkb_lksb = lksb; 611962306a36Sopenharmony_ci /* user specific pointer, just don't have it NULL for kernel locks */ 612062306a36Sopenharmony_ci if (~lkb_dflags & BIT(DLM_DFL_USER_BIT)) 612162306a36Sopenharmony_ci lkb->lkb_astparam = (void *)0xDEADBEEF; 612262306a36Sopenharmony_ci 612362306a36Sopenharmony_ci error = find_rsb(ls, name, len, 0, R_REQUEST, &r); 612462306a36Sopenharmony_ci if (error) { 612562306a36Sopenharmony_ci kfree(lksb); 612662306a36Sopenharmony_ci __put_lkb(ls, lkb); 612762306a36Sopenharmony_ci return error; 612862306a36Sopenharmony_ci } 612962306a36Sopenharmony_ci 613062306a36Sopenharmony_ci lock_rsb(r); 613162306a36Sopenharmony_ci attach_lkb(r, lkb); 613262306a36Sopenharmony_ci add_lkb(r, lkb, lkb_status); 613362306a36Sopenharmony_ci unlock_rsb(r); 613462306a36Sopenharmony_ci put_rsb(r); 613562306a36Sopenharmony_ci 613662306a36Sopenharmony_ci return 0; 613762306a36Sopenharmony_ci} 613862306a36Sopenharmony_ci 613962306a36Sopenharmony_ciint dlm_debug_add_lkb_to_waiters(struct dlm_ls *ls, uint32_t lkb_id, 614062306a36Sopenharmony_ci int mstype, int to_nodeid) 614162306a36Sopenharmony_ci{ 614262306a36Sopenharmony_ci struct dlm_lkb *lkb; 614362306a36Sopenharmony_ci int error; 614462306a36Sopenharmony_ci 614562306a36Sopenharmony_ci error = find_lkb(ls, lkb_id, &lkb); 614662306a36Sopenharmony_ci if (error) 614762306a36Sopenharmony_ci return error; 614862306a36Sopenharmony_ci 614962306a36Sopenharmony_ci error = add_to_waiters(lkb, mstype, to_nodeid); 615062306a36Sopenharmony_ci dlm_put_lkb(lkb); 615162306a36Sopenharmony_ci return error; 615262306a36Sopenharmony_ci} 615362306a36Sopenharmony_ci 6154