1ccd979bdSMark Fasheh /* -*- mode: c; c-basic-offset: 8; -*- 2ccd979bdSMark Fasheh * vim: noexpandtab sw=8 ts=8 sts=0: 3ccd979bdSMark Fasheh * 4ccd979bdSMark Fasheh * dlmglue.c 5ccd979bdSMark Fasheh * 6ccd979bdSMark Fasheh * Code which implements an OCFS2 specific interface to our DLM. 7ccd979bdSMark Fasheh * 8ccd979bdSMark Fasheh * Copyright (C) 2003, 2004 Oracle. All rights reserved. 9ccd979bdSMark Fasheh * 10ccd979bdSMark Fasheh * This program is free software; you can redistribute it and/or 11ccd979bdSMark Fasheh * modify it under the terms of the GNU General Public 12ccd979bdSMark Fasheh * License as published by the Free Software Foundation; either 13ccd979bdSMark Fasheh * version 2 of the License, or (at your option) any later version. 14ccd979bdSMark Fasheh * 15ccd979bdSMark Fasheh * This program is distributed in the hope that it will be useful, 16ccd979bdSMark Fasheh * but WITHOUT ANY WARRANTY; without even the implied warranty of 17ccd979bdSMark Fasheh * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 18ccd979bdSMark Fasheh * General Public License for more details. 19ccd979bdSMark Fasheh * 20ccd979bdSMark Fasheh * You should have received a copy of the GNU General Public 21ccd979bdSMark Fasheh * License along with this program; if not, write to the 22ccd979bdSMark Fasheh * Free Software Foundation, Inc., 59 Temple Place - Suite 330, 23ccd979bdSMark Fasheh * Boston, MA 021110-1307, USA. 24ccd979bdSMark Fasheh */ 25ccd979bdSMark Fasheh 26ccd979bdSMark Fasheh #include <linux/types.h> 27ccd979bdSMark Fasheh #include <linux/slab.h> 28ccd979bdSMark Fasheh #include <linux/highmem.h> 29ccd979bdSMark Fasheh #include <linux/mm.h> 30ccd979bdSMark Fasheh #include <linux/smp_lock.h> 31ccd979bdSMark Fasheh #include <linux/crc32.h> 32ccd979bdSMark Fasheh #include <linux/kthread.h> 33ccd979bdSMark Fasheh #include <linux/pagemap.h> 34ccd979bdSMark Fasheh #include <linux/debugfs.h> 35ccd979bdSMark Fasheh #include <linux/seq_file.h> 36ccd979bdSMark Fasheh 37ccd979bdSMark Fasheh #include <cluster/heartbeat.h> 38ccd979bdSMark Fasheh #include <cluster/nodemanager.h> 39ccd979bdSMark Fasheh #include <cluster/tcp.h> 40ccd979bdSMark Fasheh 41ccd979bdSMark Fasheh #include <dlm/dlmapi.h> 42ccd979bdSMark Fasheh 43ccd979bdSMark Fasheh #define MLOG_MASK_PREFIX ML_DLM_GLUE 44ccd979bdSMark Fasheh #include <cluster/masklog.h> 45ccd979bdSMark Fasheh 46ccd979bdSMark Fasheh #include "ocfs2.h" 47ccd979bdSMark Fasheh 48ccd979bdSMark Fasheh #include "alloc.h" 49ccd979bdSMark Fasheh #include "dlmglue.h" 50ccd979bdSMark Fasheh #include "extent_map.h" 51ccd979bdSMark Fasheh #include "heartbeat.h" 52ccd979bdSMark Fasheh #include "inode.h" 53ccd979bdSMark Fasheh #include "journal.h" 54ccd979bdSMark Fasheh #include "slot_map.h" 55ccd979bdSMark Fasheh #include "super.h" 56ccd979bdSMark Fasheh #include "uptodate.h" 57ccd979bdSMark Fasheh #include "vote.h" 58ccd979bdSMark Fasheh 59ccd979bdSMark Fasheh #include "buffer_head_io.h" 60ccd979bdSMark Fasheh 61ccd979bdSMark Fasheh struct ocfs2_mask_waiter { 62ccd979bdSMark Fasheh struct list_head mw_item; 63ccd979bdSMark Fasheh int mw_status; 64ccd979bdSMark Fasheh struct completion mw_complete; 65ccd979bdSMark Fasheh unsigned long mw_mask; 66ccd979bdSMark Fasheh unsigned long mw_goal; 67ccd979bdSMark Fasheh }; 68ccd979bdSMark Fasheh 69ccd979bdSMark Fasheh static void ocfs2_inode_ast_func(void *opaque); 70ccd979bdSMark Fasheh static void ocfs2_inode_bast_func(void *opaque, 71ccd979bdSMark Fasheh int level); 72ccd979bdSMark Fasheh static void ocfs2_super_ast_func(void *opaque); 73ccd979bdSMark Fasheh static void ocfs2_super_bast_func(void *opaque, 74ccd979bdSMark Fasheh int level); 75ccd979bdSMark Fasheh static void ocfs2_rename_ast_func(void *opaque); 76ccd979bdSMark Fasheh static void ocfs2_rename_bast_func(void *opaque, 77ccd979bdSMark Fasheh int level); 78ccd979bdSMark Fasheh 79ccd979bdSMark Fasheh /* so far, all locks have gotten along with the same unlock ast */ 80ccd979bdSMark Fasheh static void ocfs2_unlock_ast_func(void *opaque, 81ccd979bdSMark Fasheh enum dlm_status status); 82ccd979bdSMark Fasheh static int ocfs2_do_unblock_meta(struct inode *inode, 83ccd979bdSMark Fasheh int *requeue); 84ccd979bdSMark Fasheh static int ocfs2_unblock_meta(struct ocfs2_lock_res *lockres, 85ccd979bdSMark Fasheh int *requeue); 86ccd979bdSMark Fasheh static int ocfs2_unblock_data(struct ocfs2_lock_res *lockres, 87ccd979bdSMark Fasheh int *requeue); 88ccd979bdSMark Fasheh static int ocfs2_unblock_inode_lock(struct ocfs2_lock_res *lockres, 89ccd979bdSMark Fasheh int *requeue); 90ccd979bdSMark Fasheh static int ocfs2_unblock_osb_lock(struct ocfs2_lock_res *lockres, 91ccd979bdSMark Fasheh int *requeue); 92ccd979bdSMark Fasheh typedef void (ocfs2_convert_worker_t)(struct ocfs2_lock_res *, int); 93ccd979bdSMark Fasheh static int ocfs2_generic_unblock_lock(struct ocfs2_super *osb, 94ccd979bdSMark Fasheh struct ocfs2_lock_res *lockres, 95ccd979bdSMark Fasheh int *requeue, 96ccd979bdSMark Fasheh ocfs2_convert_worker_t *worker); 97ccd979bdSMark Fasheh 98ccd979bdSMark Fasheh struct ocfs2_lock_res_ops { 99ccd979bdSMark Fasheh void (*ast)(void *); 100ccd979bdSMark Fasheh void (*bast)(void *, int); 101ccd979bdSMark Fasheh void (*unlock_ast)(void *, enum dlm_status); 102ccd979bdSMark Fasheh int (*unblock)(struct ocfs2_lock_res *, int *); 103ccd979bdSMark Fasheh }; 104ccd979bdSMark Fasheh 105ccd979bdSMark Fasheh static struct ocfs2_lock_res_ops ocfs2_inode_rw_lops = { 106ccd979bdSMark Fasheh .ast = ocfs2_inode_ast_func, 107ccd979bdSMark Fasheh .bast = ocfs2_inode_bast_func, 108ccd979bdSMark Fasheh .unlock_ast = ocfs2_unlock_ast_func, 109ccd979bdSMark Fasheh .unblock = ocfs2_unblock_inode_lock, 110ccd979bdSMark Fasheh }; 111ccd979bdSMark Fasheh 112ccd979bdSMark Fasheh static struct ocfs2_lock_res_ops ocfs2_inode_meta_lops = { 113ccd979bdSMark Fasheh .ast = ocfs2_inode_ast_func, 114ccd979bdSMark Fasheh .bast = ocfs2_inode_bast_func, 115ccd979bdSMark Fasheh .unlock_ast = ocfs2_unlock_ast_func, 116ccd979bdSMark Fasheh .unblock = ocfs2_unblock_meta, 117ccd979bdSMark Fasheh }; 118ccd979bdSMark Fasheh 119ccd979bdSMark Fasheh static void ocfs2_data_convert_worker(struct ocfs2_lock_res *lockres, 120ccd979bdSMark Fasheh int blocking); 121ccd979bdSMark Fasheh 122ccd979bdSMark Fasheh static struct ocfs2_lock_res_ops ocfs2_inode_data_lops = { 123ccd979bdSMark Fasheh .ast = ocfs2_inode_ast_func, 124ccd979bdSMark Fasheh .bast = ocfs2_inode_bast_func, 125ccd979bdSMark Fasheh .unlock_ast = ocfs2_unlock_ast_func, 126ccd979bdSMark Fasheh .unblock = ocfs2_unblock_data, 127ccd979bdSMark Fasheh }; 128ccd979bdSMark Fasheh 129ccd979bdSMark Fasheh static struct ocfs2_lock_res_ops ocfs2_super_lops = { 130ccd979bdSMark Fasheh .ast = ocfs2_super_ast_func, 131ccd979bdSMark Fasheh .bast = ocfs2_super_bast_func, 132ccd979bdSMark Fasheh .unlock_ast = ocfs2_unlock_ast_func, 133ccd979bdSMark Fasheh .unblock = ocfs2_unblock_osb_lock, 134ccd979bdSMark Fasheh }; 135ccd979bdSMark Fasheh 136ccd979bdSMark Fasheh static struct ocfs2_lock_res_ops ocfs2_rename_lops = { 137ccd979bdSMark Fasheh .ast = ocfs2_rename_ast_func, 138ccd979bdSMark Fasheh .bast = ocfs2_rename_bast_func, 139ccd979bdSMark Fasheh .unlock_ast = ocfs2_unlock_ast_func, 140ccd979bdSMark Fasheh .unblock = ocfs2_unblock_osb_lock, 141ccd979bdSMark Fasheh }; 142ccd979bdSMark Fasheh 143ccd979bdSMark Fasheh static inline int ocfs2_is_inode_lock(struct ocfs2_lock_res *lockres) 144ccd979bdSMark Fasheh { 145ccd979bdSMark Fasheh return lockres->l_type == OCFS2_LOCK_TYPE_META || 146ccd979bdSMark Fasheh lockres->l_type == OCFS2_LOCK_TYPE_DATA || 147ccd979bdSMark Fasheh lockres->l_type == OCFS2_LOCK_TYPE_RW; 148ccd979bdSMark Fasheh } 149ccd979bdSMark Fasheh 150ccd979bdSMark Fasheh static inline int ocfs2_is_super_lock(struct ocfs2_lock_res *lockres) 151ccd979bdSMark Fasheh { 152ccd979bdSMark Fasheh return lockres->l_type == OCFS2_LOCK_TYPE_SUPER; 153ccd979bdSMark Fasheh } 154ccd979bdSMark Fasheh 155ccd979bdSMark Fasheh static inline int ocfs2_is_rename_lock(struct ocfs2_lock_res *lockres) 156ccd979bdSMark Fasheh { 157ccd979bdSMark Fasheh return lockres->l_type == OCFS2_LOCK_TYPE_RENAME; 158ccd979bdSMark Fasheh } 159ccd979bdSMark Fasheh 160ccd979bdSMark Fasheh static inline struct ocfs2_super *ocfs2_lock_res_super(struct ocfs2_lock_res *lockres) 161ccd979bdSMark Fasheh { 162ccd979bdSMark Fasheh BUG_ON(!ocfs2_is_super_lock(lockres) 163ccd979bdSMark Fasheh && !ocfs2_is_rename_lock(lockres)); 164ccd979bdSMark Fasheh 165ccd979bdSMark Fasheh return (struct ocfs2_super *) lockres->l_priv; 166ccd979bdSMark Fasheh } 167ccd979bdSMark Fasheh 168ccd979bdSMark Fasheh static inline struct inode *ocfs2_lock_res_inode(struct ocfs2_lock_res *lockres) 169ccd979bdSMark Fasheh { 170ccd979bdSMark Fasheh BUG_ON(!ocfs2_is_inode_lock(lockres)); 171ccd979bdSMark Fasheh 172ccd979bdSMark Fasheh return (struct inode *) lockres->l_priv; 173ccd979bdSMark Fasheh } 174ccd979bdSMark Fasheh 175ccd979bdSMark Fasheh static int ocfs2_lock_create(struct ocfs2_super *osb, 176ccd979bdSMark Fasheh struct ocfs2_lock_res *lockres, 177ccd979bdSMark Fasheh int level, 178ccd979bdSMark Fasheh int dlm_flags); 179ccd979bdSMark Fasheh static inline int ocfs2_may_continue_on_blocked_lock(struct ocfs2_lock_res *lockres, 180ccd979bdSMark Fasheh int wanted); 181ccd979bdSMark Fasheh static void ocfs2_cluster_unlock(struct ocfs2_super *osb, 182ccd979bdSMark Fasheh struct ocfs2_lock_res *lockres, 183ccd979bdSMark Fasheh int level); 184ccd979bdSMark Fasheh static inline void ocfs2_generic_handle_downconvert_action(struct ocfs2_lock_res *lockres); 185ccd979bdSMark Fasheh static inline void ocfs2_generic_handle_convert_action(struct ocfs2_lock_res *lockres); 186ccd979bdSMark Fasheh static inline void ocfs2_generic_handle_attach_action(struct ocfs2_lock_res *lockres); 187ccd979bdSMark Fasheh static int ocfs2_generic_handle_bast(struct ocfs2_lock_res *lockres, int level); 188ccd979bdSMark Fasheh static void ocfs2_schedule_blocked_lock(struct ocfs2_super *osb, 189ccd979bdSMark Fasheh struct ocfs2_lock_res *lockres); 190ccd979bdSMark Fasheh static inline void ocfs2_recover_from_dlm_error(struct ocfs2_lock_res *lockres, 191ccd979bdSMark Fasheh int convert); 192ccd979bdSMark Fasheh #define ocfs2_log_dlm_error(_func, _stat, _lockres) do { \ 193ccd979bdSMark Fasheh mlog(ML_ERROR, "Dlm error \"%s\" while calling %s on " \ 194ccd979bdSMark Fasheh "resource %s: %s\n", dlm_errname(_stat), _func, \ 195ccd979bdSMark Fasheh _lockres->l_name, dlm_errmsg(_stat)); \ 196ccd979bdSMark Fasheh } while (0) 197ccd979bdSMark Fasheh static void ocfs2_vote_on_unlock(struct ocfs2_super *osb, 198ccd979bdSMark Fasheh struct ocfs2_lock_res *lockres); 199ccd979bdSMark Fasheh static int ocfs2_meta_lock_update(struct inode *inode, 200ccd979bdSMark Fasheh struct buffer_head **bh); 201ccd979bdSMark Fasheh static void ocfs2_drop_osb_locks(struct ocfs2_super *osb); 202ccd979bdSMark Fasheh static inline int ocfs2_highest_compat_lock_level(int level); 203ccd979bdSMark Fasheh static inline int ocfs2_can_downconvert_meta_lock(struct inode *inode, 204ccd979bdSMark Fasheh struct ocfs2_lock_res *lockres, 205ccd979bdSMark Fasheh int new_level); 206ccd979bdSMark Fasheh 207ccd979bdSMark Fasheh static char *ocfs2_lock_type_strings[] = { 208ccd979bdSMark Fasheh [OCFS2_LOCK_TYPE_META] = "Meta", 209ccd979bdSMark Fasheh [OCFS2_LOCK_TYPE_DATA] = "Data", 210ccd979bdSMark Fasheh [OCFS2_LOCK_TYPE_SUPER] = "Super", 211ccd979bdSMark Fasheh [OCFS2_LOCK_TYPE_RENAME] = "Rename", 212ccd979bdSMark Fasheh /* Need to differntiate from [R]ename.. serializing writes is the 213ccd979bdSMark Fasheh * important job it does, anyway. */ 214ccd979bdSMark Fasheh [OCFS2_LOCK_TYPE_RW] = "Write/Read", 215ccd979bdSMark Fasheh }; 216ccd979bdSMark Fasheh 217ccd979bdSMark Fasheh static char *ocfs2_lock_type_string(enum ocfs2_lock_type type) 218ccd979bdSMark Fasheh { 219ccd979bdSMark Fasheh mlog_bug_on_msg(type >= OCFS2_NUM_LOCK_TYPES, "%d\n", type); 220ccd979bdSMark Fasheh return ocfs2_lock_type_strings[type]; 221ccd979bdSMark Fasheh } 222ccd979bdSMark Fasheh 223ccd979bdSMark Fasheh static void ocfs2_build_lock_name(enum ocfs2_lock_type type, 224ccd979bdSMark Fasheh u64 blkno, 225ccd979bdSMark Fasheh u32 generation, 226ccd979bdSMark Fasheh char *name) 227ccd979bdSMark Fasheh { 228ccd979bdSMark Fasheh int len; 229ccd979bdSMark Fasheh 230ccd979bdSMark Fasheh mlog_entry_void(); 231ccd979bdSMark Fasheh 232ccd979bdSMark Fasheh BUG_ON(type >= OCFS2_NUM_LOCK_TYPES); 233ccd979bdSMark Fasheh 234b0697053SMark Fasheh len = snprintf(name, OCFS2_LOCK_ID_MAX_LEN, "%c%s%016llx%08x", 235b0697053SMark Fasheh ocfs2_lock_type_char(type), OCFS2_LOCK_ID_PAD, 236b0697053SMark Fasheh (long long)blkno, generation); 237ccd979bdSMark Fasheh 238ccd979bdSMark Fasheh BUG_ON(len != (OCFS2_LOCK_ID_MAX_LEN - 1)); 239ccd979bdSMark Fasheh 240ccd979bdSMark Fasheh mlog(0, "built lock resource with name: %s\n", name); 241ccd979bdSMark Fasheh 242ccd979bdSMark Fasheh mlog_exit_void(); 243ccd979bdSMark Fasheh } 244ccd979bdSMark Fasheh 245ccd979bdSMark Fasheh static spinlock_t ocfs2_dlm_tracking_lock = SPIN_LOCK_UNLOCKED; 246ccd979bdSMark Fasheh 247ccd979bdSMark Fasheh static void ocfs2_add_lockres_tracking(struct ocfs2_lock_res *res, 248ccd979bdSMark Fasheh struct ocfs2_dlm_debug *dlm_debug) 249ccd979bdSMark Fasheh { 250ccd979bdSMark Fasheh mlog(0, "Add tracking for lockres %s\n", res->l_name); 251ccd979bdSMark Fasheh 252ccd979bdSMark Fasheh spin_lock(&ocfs2_dlm_tracking_lock); 253ccd979bdSMark Fasheh list_add(&res->l_debug_list, &dlm_debug->d_lockres_tracking); 254ccd979bdSMark Fasheh spin_unlock(&ocfs2_dlm_tracking_lock); 255ccd979bdSMark Fasheh } 256ccd979bdSMark Fasheh 257ccd979bdSMark Fasheh static void ocfs2_remove_lockres_tracking(struct ocfs2_lock_res *res) 258ccd979bdSMark Fasheh { 259ccd979bdSMark Fasheh spin_lock(&ocfs2_dlm_tracking_lock); 260ccd979bdSMark Fasheh if (!list_empty(&res->l_debug_list)) 261ccd979bdSMark Fasheh list_del_init(&res->l_debug_list); 262ccd979bdSMark Fasheh spin_unlock(&ocfs2_dlm_tracking_lock); 263ccd979bdSMark Fasheh } 264ccd979bdSMark Fasheh 265ccd979bdSMark Fasheh static void ocfs2_lock_res_init_common(struct ocfs2_super *osb, 266ccd979bdSMark Fasheh struct ocfs2_lock_res *res, 267ccd979bdSMark Fasheh enum ocfs2_lock_type type, 268ccd979bdSMark Fasheh u64 blkno, 269ccd979bdSMark Fasheh u32 generation, 270ccd979bdSMark Fasheh struct ocfs2_lock_res_ops *ops, 271ccd979bdSMark Fasheh void *priv) 272ccd979bdSMark Fasheh { 273ccd979bdSMark Fasheh ocfs2_build_lock_name(type, blkno, generation, res->l_name); 274ccd979bdSMark Fasheh 275ccd979bdSMark Fasheh res->l_type = type; 276ccd979bdSMark Fasheh res->l_ops = ops; 277ccd979bdSMark Fasheh res->l_priv = priv; 278ccd979bdSMark Fasheh 279ccd979bdSMark Fasheh res->l_level = LKM_IVMODE; 280ccd979bdSMark Fasheh res->l_requested = LKM_IVMODE; 281ccd979bdSMark Fasheh res->l_blocking = LKM_IVMODE; 282ccd979bdSMark Fasheh res->l_action = OCFS2_AST_INVALID; 283ccd979bdSMark Fasheh res->l_unlock_action = OCFS2_UNLOCK_INVALID; 284ccd979bdSMark Fasheh 285ccd979bdSMark Fasheh res->l_flags = OCFS2_LOCK_INITIALIZED; 286ccd979bdSMark Fasheh 287ccd979bdSMark Fasheh ocfs2_add_lockres_tracking(res, osb->osb_dlm_debug); 288ccd979bdSMark Fasheh } 289ccd979bdSMark Fasheh 290ccd979bdSMark Fasheh void ocfs2_lock_res_init_once(struct ocfs2_lock_res *res) 291ccd979bdSMark Fasheh { 292ccd979bdSMark Fasheh /* This also clears out the lock status block */ 293ccd979bdSMark Fasheh memset(res, 0, sizeof(struct ocfs2_lock_res)); 294ccd979bdSMark Fasheh spin_lock_init(&res->l_lock); 295ccd979bdSMark Fasheh init_waitqueue_head(&res->l_event); 296ccd979bdSMark Fasheh INIT_LIST_HEAD(&res->l_blocked_list); 297ccd979bdSMark Fasheh INIT_LIST_HEAD(&res->l_mask_waiters); 298ccd979bdSMark Fasheh } 299ccd979bdSMark Fasheh 300ccd979bdSMark Fasheh void ocfs2_inode_lock_res_init(struct ocfs2_lock_res *res, 301ccd979bdSMark Fasheh enum ocfs2_lock_type type, 302ccd979bdSMark Fasheh struct inode *inode) 303ccd979bdSMark Fasheh { 304ccd979bdSMark Fasheh struct ocfs2_lock_res_ops *ops; 305ccd979bdSMark Fasheh 306ccd979bdSMark Fasheh switch(type) { 307ccd979bdSMark Fasheh case OCFS2_LOCK_TYPE_RW: 308ccd979bdSMark Fasheh ops = &ocfs2_inode_rw_lops; 309ccd979bdSMark Fasheh break; 310ccd979bdSMark Fasheh case OCFS2_LOCK_TYPE_META: 311ccd979bdSMark Fasheh ops = &ocfs2_inode_meta_lops; 312ccd979bdSMark Fasheh break; 313ccd979bdSMark Fasheh case OCFS2_LOCK_TYPE_DATA: 314ccd979bdSMark Fasheh ops = &ocfs2_inode_data_lops; 315ccd979bdSMark Fasheh break; 316ccd979bdSMark Fasheh default: 317ccd979bdSMark Fasheh mlog_bug_on_msg(1, "type: %d\n", type); 318ccd979bdSMark Fasheh ops = NULL; /* thanks, gcc */ 319ccd979bdSMark Fasheh break; 320ccd979bdSMark Fasheh }; 321ccd979bdSMark Fasheh 322ccd979bdSMark Fasheh ocfs2_lock_res_init_common(OCFS2_SB(inode->i_sb), res, type, 323ccd979bdSMark Fasheh OCFS2_I(inode)->ip_blkno, 324ccd979bdSMark Fasheh inode->i_generation, ops, inode); 325ccd979bdSMark Fasheh } 326ccd979bdSMark Fasheh 327ccd979bdSMark Fasheh static void ocfs2_super_lock_res_init(struct ocfs2_lock_res *res, 328ccd979bdSMark Fasheh struct ocfs2_super *osb) 329ccd979bdSMark Fasheh { 330ccd979bdSMark Fasheh /* Superblock lockres doesn't come from a slab so we call init 331ccd979bdSMark Fasheh * once on it manually. */ 332ccd979bdSMark Fasheh ocfs2_lock_res_init_once(res); 333ccd979bdSMark Fasheh ocfs2_lock_res_init_common(osb, res, OCFS2_LOCK_TYPE_SUPER, 334ccd979bdSMark Fasheh OCFS2_SUPER_BLOCK_BLKNO, 0, 335ccd979bdSMark Fasheh &ocfs2_super_lops, osb); 336ccd979bdSMark Fasheh } 337ccd979bdSMark Fasheh 338ccd979bdSMark Fasheh static void ocfs2_rename_lock_res_init(struct ocfs2_lock_res *res, 339ccd979bdSMark Fasheh struct ocfs2_super *osb) 340ccd979bdSMark Fasheh { 341ccd979bdSMark Fasheh /* Rename lockres doesn't come from a slab so we call init 342ccd979bdSMark Fasheh * once on it manually. */ 343ccd979bdSMark Fasheh ocfs2_lock_res_init_once(res); 344ccd979bdSMark Fasheh ocfs2_lock_res_init_common(osb, res, OCFS2_LOCK_TYPE_RENAME, 0, 0, 345ccd979bdSMark Fasheh &ocfs2_rename_lops, osb); 346ccd979bdSMark Fasheh } 347ccd979bdSMark Fasheh 348ccd979bdSMark Fasheh void ocfs2_lock_res_free(struct ocfs2_lock_res *res) 349ccd979bdSMark Fasheh { 350ccd979bdSMark Fasheh mlog_entry_void(); 351ccd979bdSMark Fasheh 352ccd979bdSMark Fasheh if (!(res->l_flags & OCFS2_LOCK_INITIALIZED)) 353ccd979bdSMark Fasheh return; 354ccd979bdSMark Fasheh 355ccd979bdSMark Fasheh ocfs2_remove_lockres_tracking(res); 356ccd979bdSMark Fasheh 357ccd979bdSMark Fasheh mlog_bug_on_msg(!list_empty(&res->l_blocked_list), 358ccd979bdSMark Fasheh "Lockres %s is on the blocked list\n", 359ccd979bdSMark Fasheh res->l_name); 360ccd979bdSMark Fasheh mlog_bug_on_msg(!list_empty(&res->l_mask_waiters), 361ccd979bdSMark Fasheh "Lockres %s has mask waiters pending\n", 362ccd979bdSMark Fasheh res->l_name); 363ccd979bdSMark Fasheh mlog_bug_on_msg(spin_is_locked(&res->l_lock), 364ccd979bdSMark Fasheh "Lockres %s is locked\n", 365ccd979bdSMark Fasheh res->l_name); 366ccd979bdSMark Fasheh mlog_bug_on_msg(res->l_ro_holders, 367ccd979bdSMark Fasheh "Lockres %s has %u ro holders\n", 368ccd979bdSMark Fasheh res->l_name, res->l_ro_holders); 369ccd979bdSMark Fasheh mlog_bug_on_msg(res->l_ex_holders, 370ccd979bdSMark Fasheh "Lockres %s has %u ex holders\n", 371ccd979bdSMark Fasheh res->l_name, res->l_ex_holders); 372ccd979bdSMark Fasheh 373ccd979bdSMark Fasheh /* Need to clear out the lock status block for the dlm */ 374ccd979bdSMark Fasheh memset(&res->l_lksb, 0, sizeof(res->l_lksb)); 375ccd979bdSMark Fasheh 376ccd979bdSMark Fasheh res->l_flags = 0UL; 377ccd979bdSMark Fasheh mlog_exit_void(); 378ccd979bdSMark Fasheh } 379ccd979bdSMark Fasheh 380ccd979bdSMark Fasheh static inline void ocfs2_inc_holders(struct ocfs2_lock_res *lockres, 381ccd979bdSMark Fasheh int level) 382ccd979bdSMark Fasheh { 383ccd979bdSMark Fasheh mlog_entry_void(); 384ccd979bdSMark Fasheh 385ccd979bdSMark Fasheh BUG_ON(!lockres); 386ccd979bdSMark Fasheh 387ccd979bdSMark Fasheh switch(level) { 388ccd979bdSMark Fasheh case LKM_EXMODE: 389ccd979bdSMark Fasheh lockres->l_ex_holders++; 390ccd979bdSMark Fasheh break; 391ccd979bdSMark Fasheh case LKM_PRMODE: 392ccd979bdSMark Fasheh lockres->l_ro_holders++; 393ccd979bdSMark Fasheh break; 394ccd979bdSMark Fasheh default: 395ccd979bdSMark Fasheh BUG(); 396ccd979bdSMark Fasheh } 397ccd979bdSMark Fasheh 398ccd979bdSMark Fasheh mlog_exit_void(); 399ccd979bdSMark Fasheh } 400ccd979bdSMark Fasheh 401ccd979bdSMark Fasheh static inline void ocfs2_dec_holders(struct ocfs2_lock_res *lockres, 402ccd979bdSMark Fasheh int level) 403ccd979bdSMark Fasheh { 404ccd979bdSMark Fasheh mlog_entry_void(); 405ccd979bdSMark Fasheh 406ccd979bdSMark Fasheh BUG_ON(!lockres); 407ccd979bdSMark Fasheh 408ccd979bdSMark Fasheh switch(level) { 409ccd979bdSMark Fasheh case LKM_EXMODE: 410ccd979bdSMark Fasheh BUG_ON(!lockres->l_ex_holders); 411ccd979bdSMark Fasheh lockres->l_ex_holders--; 412ccd979bdSMark Fasheh break; 413ccd979bdSMark Fasheh case LKM_PRMODE: 414ccd979bdSMark Fasheh BUG_ON(!lockres->l_ro_holders); 415ccd979bdSMark Fasheh lockres->l_ro_holders--; 416ccd979bdSMark Fasheh break; 417ccd979bdSMark Fasheh default: 418ccd979bdSMark Fasheh BUG(); 419ccd979bdSMark Fasheh } 420ccd979bdSMark Fasheh mlog_exit_void(); 421ccd979bdSMark Fasheh } 422ccd979bdSMark Fasheh 423ccd979bdSMark Fasheh /* WARNING: This function lives in a world where the only three lock 424ccd979bdSMark Fasheh * levels are EX, PR, and NL. It *will* have to be adjusted when more 425ccd979bdSMark Fasheh * lock types are added. */ 426ccd979bdSMark Fasheh static inline int ocfs2_highest_compat_lock_level(int level) 427ccd979bdSMark Fasheh { 428ccd979bdSMark Fasheh int new_level = LKM_EXMODE; 429ccd979bdSMark Fasheh 430ccd979bdSMark Fasheh if (level == LKM_EXMODE) 431ccd979bdSMark Fasheh new_level = LKM_NLMODE; 432ccd979bdSMark Fasheh else if (level == LKM_PRMODE) 433ccd979bdSMark Fasheh new_level = LKM_PRMODE; 434ccd979bdSMark Fasheh return new_level; 435ccd979bdSMark Fasheh } 436ccd979bdSMark Fasheh 437ccd979bdSMark Fasheh static void lockres_set_flags(struct ocfs2_lock_res *lockres, 438ccd979bdSMark Fasheh unsigned long newflags) 439ccd979bdSMark Fasheh { 440ccd979bdSMark Fasheh struct list_head *pos, *tmp; 441ccd979bdSMark Fasheh struct ocfs2_mask_waiter *mw; 442ccd979bdSMark Fasheh 443ccd979bdSMark Fasheh assert_spin_locked(&lockres->l_lock); 444ccd979bdSMark Fasheh 445ccd979bdSMark Fasheh lockres->l_flags = newflags; 446ccd979bdSMark Fasheh 447ccd979bdSMark Fasheh list_for_each_safe(pos, tmp, &lockres->l_mask_waiters) { 448ccd979bdSMark Fasheh mw = list_entry(pos, struct ocfs2_mask_waiter, mw_item); 449ccd979bdSMark Fasheh if ((lockres->l_flags & mw->mw_mask) != mw->mw_goal) 450ccd979bdSMark Fasheh continue; 451ccd979bdSMark Fasheh 452ccd979bdSMark Fasheh list_del_init(&mw->mw_item); 453ccd979bdSMark Fasheh mw->mw_status = 0; 454ccd979bdSMark Fasheh complete(&mw->mw_complete); 455ccd979bdSMark Fasheh } 456ccd979bdSMark Fasheh } 457ccd979bdSMark Fasheh static void lockres_or_flags(struct ocfs2_lock_res *lockres, unsigned long or) 458ccd979bdSMark Fasheh { 459ccd979bdSMark Fasheh lockres_set_flags(lockres, lockres->l_flags | or); 460ccd979bdSMark Fasheh } 461ccd979bdSMark Fasheh static void lockres_clear_flags(struct ocfs2_lock_res *lockres, 462ccd979bdSMark Fasheh unsigned long clear) 463ccd979bdSMark Fasheh { 464ccd979bdSMark Fasheh lockres_set_flags(lockres, lockres->l_flags & ~clear); 465ccd979bdSMark Fasheh } 466ccd979bdSMark Fasheh 467ccd979bdSMark Fasheh static inline void ocfs2_generic_handle_downconvert_action(struct ocfs2_lock_res *lockres) 468ccd979bdSMark Fasheh { 469ccd979bdSMark Fasheh mlog_entry_void(); 470ccd979bdSMark Fasheh 471ccd979bdSMark Fasheh BUG_ON(!(lockres->l_flags & OCFS2_LOCK_BUSY)); 472ccd979bdSMark Fasheh BUG_ON(!(lockres->l_flags & OCFS2_LOCK_ATTACHED)); 473ccd979bdSMark Fasheh BUG_ON(!(lockres->l_flags & OCFS2_LOCK_BLOCKED)); 474ccd979bdSMark Fasheh BUG_ON(lockres->l_blocking <= LKM_NLMODE); 475ccd979bdSMark Fasheh 476ccd979bdSMark Fasheh lockres->l_level = lockres->l_requested; 477ccd979bdSMark Fasheh if (lockres->l_level <= 478ccd979bdSMark Fasheh ocfs2_highest_compat_lock_level(lockres->l_blocking)) { 479ccd979bdSMark Fasheh lockres->l_blocking = LKM_NLMODE; 480ccd979bdSMark Fasheh lockres_clear_flags(lockres, OCFS2_LOCK_BLOCKED); 481ccd979bdSMark Fasheh } 482ccd979bdSMark Fasheh lockres_clear_flags(lockres, OCFS2_LOCK_BUSY); 483ccd979bdSMark Fasheh 484ccd979bdSMark Fasheh mlog_exit_void(); 485ccd979bdSMark Fasheh } 486ccd979bdSMark Fasheh 487ccd979bdSMark Fasheh static inline void ocfs2_generic_handle_convert_action(struct ocfs2_lock_res *lockres) 488ccd979bdSMark Fasheh { 489ccd979bdSMark Fasheh mlog_entry_void(); 490ccd979bdSMark Fasheh 491ccd979bdSMark Fasheh BUG_ON(!(lockres->l_flags & OCFS2_LOCK_BUSY)); 492ccd979bdSMark Fasheh BUG_ON(!(lockres->l_flags & OCFS2_LOCK_ATTACHED)); 493ccd979bdSMark Fasheh 494ccd979bdSMark Fasheh /* Convert from RO to EX doesn't really need anything as our 495ccd979bdSMark Fasheh * information is already up to data. Convert from NL to 496ccd979bdSMark Fasheh * *anything* however should mark ourselves as needing an 497ccd979bdSMark Fasheh * update */ 498ccd979bdSMark Fasheh if (lockres->l_level == LKM_NLMODE) 499ccd979bdSMark Fasheh lockres_or_flags(lockres, OCFS2_LOCK_NEEDS_REFRESH); 500ccd979bdSMark Fasheh 501ccd979bdSMark Fasheh lockres->l_level = lockres->l_requested; 502ccd979bdSMark Fasheh lockres_clear_flags(lockres, OCFS2_LOCK_BUSY); 503ccd979bdSMark Fasheh 504ccd979bdSMark Fasheh mlog_exit_void(); 505ccd979bdSMark Fasheh } 506ccd979bdSMark Fasheh 507ccd979bdSMark Fasheh static inline void ocfs2_generic_handle_attach_action(struct ocfs2_lock_res *lockres) 508ccd979bdSMark Fasheh { 509ccd979bdSMark Fasheh mlog_entry_void(); 510ccd979bdSMark Fasheh 511ccd979bdSMark Fasheh BUG_ON((!lockres->l_flags & OCFS2_LOCK_BUSY)); 512ccd979bdSMark Fasheh BUG_ON(lockres->l_flags & OCFS2_LOCK_ATTACHED); 513ccd979bdSMark Fasheh 514ccd979bdSMark Fasheh if (lockres->l_requested > LKM_NLMODE && 515ccd979bdSMark Fasheh !(lockres->l_flags & OCFS2_LOCK_LOCAL)) 516ccd979bdSMark Fasheh lockres_or_flags(lockres, OCFS2_LOCK_NEEDS_REFRESH); 517ccd979bdSMark Fasheh 518ccd979bdSMark Fasheh lockres->l_level = lockres->l_requested; 519ccd979bdSMark Fasheh lockres_or_flags(lockres, OCFS2_LOCK_ATTACHED); 520ccd979bdSMark Fasheh lockres_clear_flags(lockres, OCFS2_LOCK_BUSY); 521ccd979bdSMark Fasheh 522ccd979bdSMark Fasheh mlog_exit_void(); 523ccd979bdSMark Fasheh } 524ccd979bdSMark Fasheh 525ccd979bdSMark Fasheh static void ocfs2_inode_ast_func(void *opaque) 526ccd979bdSMark Fasheh { 527ccd979bdSMark Fasheh struct ocfs2_lock_res *lockres = opaque; 528ccd979bdSMark Fasheh struct inode *inode; 529ccd979bdSMark Fasheh struct dlm_lockstatus *lksb; 530ccd979bdSMark Fasheh unsigned long flags; 531ccd979bdSMark Fasheh 532ccd979bdSMark Fasheh mlog_entry_void(); 533ccd979bdSMark Fasheh 534ccd979bdSMark Fasheh inode = ocfs2_lock_res_inode(lockres); 535ccd979bdSMark Fasheh 536b0697053SMark Fasheh mlog(0, "AST fired for inode %llu, l_action = %u, type = %s\n", 537b0697053SMark Fasheh (unsigned long long)OCFS2_I(inode)->ip_blkno, lockres->l_action, 538ccd979bdSMark Fasheh ocfs2_lock_type_string(lockres->l_type)); 539ccd979bdSMark Fasheh 540ccd979bdSMark Fasheh BUG_ON(!ocfs2_is_inode_lock(lockres)); 541ccd979bdSMark Fasheh 542ccd979bdSMark Fasheh spin_lock_irqsave(&lockres->l_lock, flags); 543ccd979bdSMark Fasheh 544ccd979bdSMark Fasheh lksb = &(lockres->l_lksb); 545ccd979bdSMark Fasheh if (lksb->status != DLM_NORMAL) { 546ccd979bdSMark Fasheh mlog(ML_ERROR, "ocfs2_inode_ast_func: lksb status value of %u " 547b0697053SMark Fasheh "on inode %llu\n", lksb->status, 548b0697053SMark Fasheh (unsigned long long)OCFS2_I(inode)->ip_blkno); 549ccd979bdSMark Fasheh spin_unlock_irqrestore(&lockres->l_lock, flags); 550ccd979bdSMark Fasheh mlog_exit_void(); 551ccd979bdSMark Fasheh return; 552ccd979bdSMark Fasheh } 553ccd979bdSMark Fasheh 554ccd979bdSMark Fasheh switch(lockres->l_action) { 555ccd979bdSMark Fasheh case OCFS2_AST_ATTACH: 556ccd979bdSMark Fasheh ocfs2_generic_handle_attach_action(lockres); 557ccd979bdSMark Fasheh lockres_clear_flags(lockres, OCFS2_LOCK_LOCAL); 558ccd979bdSMark Fasheh break; 559ccd979bdSMark Fasheh case OCFS2_AST_CONVERT: 560ccd979bdSMark Fasheh ocfs2_generic_handle_convert_action(lockres); 561ccd979bdSMark Fasheh break; 562ccd979bdSMark Fasheh case OCFS2_AST_DOWNCONVERT: 563ccd979bdSMark Fasheh ocfs2_generic_handle_downconvert_action(lockres); 564ccd979bdSMark Fasheh break; 565ccd979bdSMark Fasheh default: 566ccd979bdSMark Fasheh mlog(ML_ERROR, "lockres %s: ast fired with invalid action: %u " 567ccd979bdSMark Fasheh "lockres flags = 0x%lx, unlock action: %u\n", 568ccd979bdSMark Fasheh lockres->l_name, lockres->l_action, lockres->l_flags, 569ccd979bdSMark Fasheh lockres->l_unlock_action); 570ccd979bdSMark Fasheh 571ccd979bdSMark Fasheh BUG(); 572ccd979bdSMark Fasheh } 573ccd979bdSMark Fasheh 574ccd979bdSMark Fasheh /* data and rw locking ignores refresh flag for now. */ 575ccd979bdSMark Fasheh if (lockres->l_type != OCFS2_LOCK_TYPE_META) 576ccd979bdSMark Fasheh lockres_clear_flags(lockres, OCFS2_LOCK_NEEDS_REFRESH); 577ccd979bdSMark Fasheh 578ccd979bdSMark Fasheh /* set it to something invalid so if we get called again we 579ccd979bdSMark Fasheh * can catch it. */ 580ccd979bdSMark Fasheh lockres->l_action = OCFS2_AST_INVALID; 581ccd979bdSMark Fasheh spin_unlock_irqrestore(&lockres->l_lock, flags); 582ccd979bdSMark Fasheh wake_up(&lockres->l_event); 583ccd979bdSMark Fasheh 584ccd979bdSMark Fasheh mlog_exit_void(); 585ccd979bdSMark Fasheh } 586ccd979bdSMark Fasheh 587ccd979bdSMark Fasheh static int ocfs2_generic_handle_bast(struct ocfs2_lock_res *lockres, 588ccd979bdSMark Fasheh int level) 589ccd979bdSMark Fasheh { 590ccd979bdSMark Fasheh int needs_downconvert = 0; 591ccd979bdSMark Fasheh mlog_entry_void(); 592ccd979bdSMark Fasheh 593ccd979bdSMark Fasheh assert_spin_locked(&lockres->l_lock); 594ccd979bdSMark Fasheh 595ccd979bdSMark Fasheh lockres_or_flags(lockres, OCFS2_LOCK_BLOCKED); 596ccd979bdSMark Fasheh 597ccd979bdSMark Fasheh if (level > lockres->l_blocking) { 598ccd979bdSMark Fasheh /* only schedule a downconvert if we haven't already scheduled 599ccd979bdSMark Fasheh * one that goes low enough to satisfy the level we're 600ccd979bdSMark Fasheh * blocking. this also catches the case where we get 601ccd979bdSMark Fasheh * duplicate BASTs */ 602ccd979bdSMark Fasheh if (ocfs2_highest_compat_lock_level(level) < 603ccd979bdSMark Fasheh ocfs2_highest_compat_lock_level(lockres->l_blocking)) 604ccd979bdSMark Fasheh needs_downconvert = 1; 605ccd979bdSMark Fasheh 606ccd979bdSMark Fasheh lockres->l_blocking = level; 607ccd979bdSMark Fasheh } 608ccd979bdSMark Fasheh 609ccd979bdSMark Fasheh mlog_exit(needs_downconvert); 610ccd979bdSMark Fasheh return needs_downconvert; 611ccd979bdSMark Fasheh } 612ccd979bdSMark Fasheh 613ccd979bdSMark Fasheh static void ocfs2_generic_bast_func(struct ocfs2_super *osb, 614ccd979bdSMark Fasheh struct ocfs2_lock_res *lockres, 615ccd979bdSMark Fasheh int level) 616ccd979bdSMark Fasheh { 617ccd979bdSMark Fasheh int needs_downconvert; 618ccd979bdSMark Fasheh unsigned long flags; 619ccd979bdSMark Fasheh 620ccd979bdSMark Fasheh mlog_entry_void(); 621ccd979bdSMark Fasheh 622ccd979bdSMark Fasheh BUG_ON(level <= LKM_NLMODE); 623ccd979bdSMark Fasheh 624ccd979bdSMark Fasheh spin_lock_irqsave(&lockres->l_lock, flags); 625ccd979bdSMark Fasheh needs_downconvert = ocfs2_generic_handle_bast(lockres, level); 626ccd979bdSMark Fasheh if (needs_downconvert) 627ccd979bdSMark Fasheh ocfs2_schedule_blocked_lock(osb, lockres); 628ccd979bdSMark Fasheh spin_unlock_irqrestore(&lockres->l_lock, flags); 629ccd979bdSMark Fasheh 630ccd979bdSMark Fasheh ocfs2_kick_vote_thread(osb); 631ccd979bdSMark Fasheh 632ccd979bdSMark Fasheh wake_up(&lockres->l_event); 633ccd979bdSMark Fasheh mlog_exit_void(); 634ccd979bdSMark Fasheh } 635ccd979bdSMark Fasheh 636ccd979bdSMark Fasheh static void ocfs2_inode_bast_func(void *opaque, int level) 637ccd979bdSMark Fasheh { 638ccd979bdSMark Fasheh struct ocfs2_lock_res *lockres = opaque; 639ccd979bdSMark Fasheh struct inode *inode; 640ccd979bdSMark Fasheh struct ocfs2_super *osb; 641ccd979bdSMark Fasheh 642ccd979bdSMark Fasheh mlog_entry_void(); 643ccd979bdSMark Fasheh 644ccd979bdSMark Fasheh BUG_ON(!ocfs2_is_inode_lock(lockres)); 645ccd979bdSMark Fasheh 646ccd979bdSMark Fasheh inode = ocfs2_lock_res_inode(lockres); 647ccd979bdSMark Fasheh osb = OCFS2_SB(inode->i_sb); 648ccd979bdSMark Fasheh 649b0697053SMark Fasheh mlog(0, "BAST fired for inode %llu, blocking %d, level %d type %s\n", 650b0697053SMark Fasheh (unsigned long long)OCFS2_I(inode)->ip_blkno, level, 651b0697053SMark Fasheh lockres->l_level, ocfs2_lock_type_string(lockres->l_type)); 652ccd979bdSMark Fasheh 653ccd979bdSMark Fasheh ocfs2_generic_bast_func(osb, lockres, level); 654ccd979bdSMark Fasheh 655ccd979bdSMark Fasheh mlog_exit_void(); 656ccd979bdSMark Fasheh } 657ccd979bdSMark Fasheh 658ccd979bdSMark Fasheh static void ocfs2_generic_ast_func(struct ocfs2_lock_res *lockres, 659ccd979bdSMark Fasheh int ignore_refresh) 660ccd979bdSMark Fasheh { 661ccd979bdSMark Fasheh struct dlm_lockstatus *lksb = &lockres->l_lksb; 662ccd979bdSMark Fasheh unsigned long flags; 663ccd979bdSMark Fasheh 664ccd979bdSMark Fasheh spin_lock_irqsave(&lockres->l_lock, flags); 665ccd979bdSMark Fasheh 666ccd979bdSMark Fasheh if (lksb->status != DLM_NORMAL) { 667ccd979bdSMark Fasheh mlog(ML_ERROR, "lockres %s: lksb status value of %u!\n", 668ccd979bdSMark Fasheh lockres->l_name, lksb->status); 669ccd979bdSMark Fasheh spin_unlock_irqrestore(&lockres->l_lock, flags); 670ccd979bdSMark Fasheh return; 671ccd979bdSMark Fasheh } 672ccd979bdSMark Fasheh 673ccd979bdSMark Fasheh switch(lockres->l_action) { 674ccd979bdSMark Fasheh case OCFS2_AST_ATTACH: 675ccd979bdSMark Fasheh ocfs2_generic_handle_attach_action(lockres); 676ccd979bdSMark Fasheh break; 677ccd979bdSMark Fasheh case OCFS2_AST_CONVERT: 678ccd979bdSMark Fasheh ocfs2_generic_handle_convert_action(lockres); 679ccd979bdSMark Fasheh break; 680ccd979bdSMark Fasheh case OCFS2_AST_DOWNCONVERT: 681ccd979bdSMark Fasheh ocfs2_generic_handle_downconvert_action(lockres); 682ccd979bdSMark Fasheh break; 683ccd979bdSMark Fasheh default: 684ccd979bdSMark Fasheh BUG(); 685ccd979bdSMark Fasheh } 686ccd979bdSMark Fasheh 687ccd979bdSMark Fasheh if (ignore_refresh) 688ccd979bdSMark Fasheh lockres_clear_flags(lockres, OCFS2_LOCK_NEEDS_REFRESH); 689ccd979bdSMark Fasheh 690ccd979bdSMark Fasheh /* set it to something invalid so if we get called again we 691ccd979bdSMark Fasheh * can catch it. */ 692ccd979bdSMark Fasheh lockres->l_action = OCFS2_AST_INVALID; 693ccd979bdSMark Fasheh spin_unlock_irqrestore(&lockres->l_lock, flags); 694ccd979bdSMark Fasheh 695ccd979bdSMark Fasheh wake_up(&lockres->l_event); 696ccd979bdSMark Fasheh } 697ccd979bdSMark Fasheh 698ccd979bdSMark Fasheh static void ocfs2_super_ast_func(void *opaque) 699ccd979bdSMark Fasheh { 700ccd979bdSMark Fasheh struct ocfs2_lock_res *lockres = opaque; 701ccd979bdSMark Fasheh 702ccd979bdSMark Fasheh mlog_entry_void(); 703ccd979bdSMark Fasheh mlog(0, "Superblock AST fired\n"); 704ccd979bdSMark Fasheh 705ccd979bdSMark Fasheh BUG_ON(!ocfs2_is_super_lock(lockres)); 706ccd979bdSMark Fasheh ocfs2_generic_ast_func(lockres, 0); 707ccd979bdSMark Fasheh 708ccd979bdSMark Fasheh mlog_exit_void(); 709ccd979bdSMark Fasheh } 710ccd979bdSMark Fasheh 711ccd979bdSMark Fasheh static void ocfs2_super_bast_func(void *opaque, 712ccd979bdSMark Fasheh int level) 713ccd979bdSMark Fasheh { 714ccd979bdSMark Fasheh struct ocfs2_lock_res *lockres = opaque; 715ccd979bdSMark Fasheh struct ocfs2_super *osb; 716ccd979bdSMark Fasheh 717ccd979bdSMark Fasheh mlog_entry_void(); 718ccd979bdSMark Fasheh mlog(0, "Superblock BAST fired\n"); 719ccd979bdSMark Fasheh 720ccd979bdSMark Fasheh BUG_ON(!ocfs2_is_super_lock(lockres)); 721ccd979bdSMark Fasheh osb = ocfs2_lock_res_super(lockres); 722ccd979bdSMark Fasheh ocfs2_generic_bast_func(osb, lockres, level); 723ccd979bdSMark Fasheh 724ccd979bdSMark Fasheh mlog_exit_void(); 725ccd979bdSMark Fasheh } 726ccd979bdSMark Fasheh 727ccd979bdSMark Fasheh static void ocfs2_rename_ast_func(void *opaque) 728ccd979bdSMark Fasheh { 729ccd979bdSMark Fasheh struct ocfs2_lock_res *lockres = opaque; 730ccd979bdSMark Fasheh 731ccd979bdSMark Fasheh mlog_entry_void(); 732ccd979bdSMark Fasheh 733ccd979bdSMark Fasheh mlog(0, "Rename AST fired\n"); 734ccd979bdSMark Fasheh 735ccd979bdSMark Fasheh BUG_ON(!ocfs2_is_rename_lock(lockres)); 736ccd979bdSMark Fasheh 737ccd979bdSMark Fasheh ocfs2_generic_ast_func(lockres, 1); 738ccd979bdSMark Fasheh 739ccd979bdSMark Fasheh mlog_exit_void(); 740ccd979bdSMark Fasheh } 741ccd979bdSMark Fasheh 742ccd979bdSMark Fasheh static void ocfs2_rename_bast_func(void *opaque, 743ccd979bdSMark Fasheh int level) 744ccd979bdSMark Fasheh { 745ccd979bdSMark Fasheh struct ocfs2_lock_res *lockres = opaque; 746ccd979bdSMark Fasheh struct ocfs2_super *osb; 747ccd979bdSMark Fasheh 748ccd979bdSMark Fasheh mlog_entry_void(); 749ccd979bdSMark Fasheh 750ccd979bdSMark Fasheh mlog(0, "Rename BAST fired\n"); 751ccd979bdSMark Fasheh 752ccd979bdSMark Fasheh BUG_ON(!ocfs2_is_rename_lock(lockres)); 753ccd979bdSMark Fasheh 754ccd979bdSMark Fasheh osb = ocfs2_lock_res_super(lockres); 755ccd979bdSMark Fasheh ocfs2_generic_bast_func(osb, lockres, level); 756ccd979bdSMark Fasheh 757ccd979bdSMark Fasheh mlog_exit_void(); 758ccd979bdSMark Fasheh } 759ccd979bdSMark Fasheh 760ccd979bdSMark Fasheh static inline void ocfs2_recover_from_dlm_error(struct ocfs2_lock_res *lockres, 761ccd979bdSMark Fasheh int convert) 762ccd979bdSMark Fasheh { 763ccd979bdSMark Fasheh unsigned long flags; 764ccd979bdSMark Fasheh 765ccd979bdSMark Fasheh mlog_entry_void(); 766ccd979bdSMark Fasheh spin_lock_irqsave(&lockres->l_lock, flags); 767ccd979bdSMark Fasheh lockres_clear_flags(lockres, OCFS2_LOCK_BUSY); 768ccd979bdSMark Fasheh if (convert) 769ccd979bdSMark Fasheh lockres->l_action = OCFS2_AST_INVALID; 770ccd979bdSMark Fasheh else 771ccd979bdSMark Fasheh lockres->l_unlock_action = OCFS2_UNLOCK_INVALID; 772ccd979bdSMark Fasheh spin_unlock_irqrestore(&lockres->l_lock, flags); 773ccd979bdSMark Fasheh 774ccd979bdSMark Fasheh wake_up(&lockres->l_event); 775ccd979bdSMark Fasheh mlog_exit_void(); 776ccd979bdSMark Fasheh } 777ccd979bdSMark Fasheh 778ccd979bdSMark Fasheh /* Note: If we detect another process working on the lock (i.e., 779ccd979bdSMark Fasheh * OCFS2_LOCK_BUSY), we'll bail out returning 0. It's up to the caller 780ccd979bdSMark Fasheh * to do the right thing in that case. 781ccd979bdSMark Fasheh */ 782ccd979bdSMark Fasheh static int ocfs2_lock_create(struct ocfs2_super *osb, 783ccd979bdSMark Fasheh struct ocfs2_lock_res *lockres, 784ccd979bdSMark Fasheh int level, 785ccd979bdSMark Fasheh int dlm_flags) 786ccd979bdSMark Fasheh { 787ccd979bdSMark Fasheh int ret = 0; 788ccd979bdSMark Fasheh enum dlm_status status; 789ccd979bdSMark Fasheh unsigned long flags; 790ccd979bdSMark Fasheh 791ccd979bdSMark Fasheh mlog_entry_void(); 792ccd979bdSMark Fasheh 793ccd979bdSMark Fasheh mlog(0, "lock %s, level = %d, flags = %d\n", lockres->l_name, level, 794ccd979bdSMark Fasheh dlm_flags); 795ccd979bdSMark Fasheh 796ccd979bdSMark Fasheh spin_lock_irqsave(&lockres->l_lock, flags); 797ccd979bdSMark Fasheh if ((lockres->l_flags & OCFS2_LOCK_ATTACHED) || 798ccd979bdSMark Fasheh (lockres->l_flags & OCFS2_LOCK_BUSY)) { 799ccd979bdSMark Fasheh spin_unlock_irqrestore(&lockres->l_lock, flags); 800ccd979bdSMark Fasheh goto bail; 801ccd979bdSMark Fasheh } 802ccd979bdSMark Fasheh 803ccd979bdSMark Fasheh lockres->l_action = OCFS2_AST_ATTACH; 804ccd979bdSMark Fasheh lockres->l_requested = level; 805ccd979bdSMark Fasheh lockres_or_flags(lockres, OCFS2_LOCK_BUSY); 806ccd979bdSMark Fasheh spin_unlock_irqrestore(&lockres->l_lock, flags); 807ccd979bdSMark Fasheh 808ccd979bdSMark Fasheh status = dlmlock(osb->dlm, 809ccd979bdSMark Fasheh level, 810ccd979bdSMark Fasheh &lockres->l_lksb, 811ccd979bdSMark Fasheh dlm_flags, 812ccd979bdSMark Fasheh lockres->l_name, 813ccd979bdSMark Fasheh lockres->l_ops->ast, 814ccd979bdSMark Fasheh lockres, 815ccd979bdSMark Fasheh lockres->l_ops->bast); 816ccd979bdSMark Fasheh if (status != DLM_NORMAL) { 817ccd979bdSMark Fasheh ocfs2_log_dlm_error("dlmlock", status, lockres); 818ccd979bdSMark Fasheh ret = -EINVAL; 819ccd979bdSMark Fasheh ocfs2_recover_from_dlm_error(lockres, 1); 820ccd979bdSMark Fasheh } 821ccd979bdSMark Fasheh 822ccd979bdSMark Fasheh mlog(0, "lock %s, successfull return from dlmlock\n", lockres->l_name); 823ccd979bdSMark Fasheh 824ccd979bdSMark Fasheh bail: 825ccd979bdSMark Fasheh mlog_exit(ret); 826ccd979bdSMark Fasheh return ret; 827ccd979bdSMark Fasheh } 828ccd979bdSMark Fasheh 829ccd979bdSMark Fasheh static inline int ocfs2_check_wait_flag(struct ocfs2_lock_res *lockres, 830ccd979bdSMark Fasheh int flag) 831ccd979bdSMark Fasheh { 832ccd979bdSMark Fasheh unsigned long flags; 833ccd979bdSMark Fasheh int ret; 834ccd979bdSMark Fasheh 835ccd979bdSMark Fasheh spin_lock_irqsave(&lockres->l_lock, flags); 836ccd979bdSMark Fasheh ret = lockres->l_flags & flag; 837ccd979bdSMark Fasheh spin_unlock_irqrestore(&lockres->l_lock, flags); 838ccd979bdSMark Fasheh 839ccd979bdSMark Fasheh return ret; 840ccd979bdSMark Fasheh } 841ccd979bdSMark Fasheh 842ccd979bdSMark Fasheh static inline void ocfs2_wait_on_busy_lock(struct ocfs2_lock_res *lockres) 843ccd979bdSMark Fasheh 844ccd979bdSMark Fasheh { 845ccd979bdSMark Fasheh wait_event(lockres->l_event, 846ccd979bdSMark Fasheh !ocfs2_check_wait_flag(lockres, OCFS2_LOCK_BUSY)); 847ccd979bdSMark Fasheh } 848ccd979bdSMark Fasheh 849ccd979bdSMark Fasheh static inline void ocfs2_wait_on_refreshing_lock(struct ocfs2_lock_res *lockres) 850ccd979bdSMark Fasheh 851ccd979bdSMark Fasheh { 852ccd979bdSMark Fasheh wait_event(lockres->l_event, 853ccd979bdSMark Fasheh !ocfs2_check_wait_flag(lockres, OCFS2_LOCK_REFRESHING)); 854ccd979bdSMark Fasheh } 855ccd979bdSMark Fasheh 856ccd979bdSMark Fasheh /* predict what lock level we'll be dropping down to on behalf 857ccd979bdSMark Fasheh * of another node, and return true if the currently wanted 858ccd979bdSMark Fasheh * level will be compatible with it. */ 859ccd979bdSMark Fasheh static inline int ocfs2_may_continue_on_blocked_lock(struct ocfs2_lock_res *lockres, 860ccd979bdSMark Fasheh int wanted) 861ccd979bdSMark Fasheh { 862ccd979bdSMark Fasheh BUG_ON(!(lockres->l_flags & OCFS2_LOCK_BLOCKED)); 863ccd979bdSMark Fasheh 864ccd979bdSMark Fasheh return wanted <= ocfs2_highest_compat_lock_level(lockres->l_blocking); 865ccd979bdSMark Fasheh } 866ccd979bdSMark Fasheh 867ccd979bdSMark Fasheh static void ocfs2_init_mask_waiter(struct ocfs2_mask_waiter *mw) 868ccd979bdSMark Fasheh { 869ccd979bdSMark Fasheh INIT_LIST_HEAD(&mw->mw_item); 870ccd979bdSMark Fasheh init_completion(&mw->mw_complete); 871ccd979bdSMark Fasheh } 872ccd979bdSMark Fasheh 873ccd979bdSMark Fasheh static int ocfs2_wait_for_mask(struct ocfs2_mask_waiter *mw) 874ccd979bdSMark Fasheh { 875ccd979bdSMark Fasheh wait_for_completion(&mw->mw_complete); 876ccd979bdSMark Fasheh /* Re-arm the completion in case we want to wait on it again */ 877ccd979bdSMark Fasheh INIT_COMPLETION(mw->mw_complete); 878ccd979bdSMark Fasheh return mw->mw_status; 879ccd979bdSMark Fasheh } 880ccd979bdSMark Fasheh 881ccd979bdSMark Fasheh static void lockres_add_mask_waiter(struct ocfs2_lock_res *lockres, 882ccd979bdSMark Fasheh struct ocfs2_mask_waiter *mw, 883ccd979bdSMark Fasheh unsigned long mask, 884ccd979bdSMark Fasheh unsigned long goal) 885ccd979bdSMark Fasheh { 886ccd979bdSMark Fasheh BUG_ON(!list_empty(&mw->mw_item)); 887ccd979bdSMark Fasheh 888ccd979bdSMark Fasheh assert_spin_locked(&lockres->l_lock); 889ccd979bdSMark Fasheh 890ccd979bdSMark Fasheh list_add_tail(&mw->mw_item, &lockres->l_mask_waiters); 891ccd979bdSMark Fasheh mw->mw_mask = mask; 892ccd979bdSMark Fasheh mw->mw_goal = goal; 893ccd979bdSMark Fasheh } 894ccd979bdSMark Fasheh 895ccd979bdSMark Fasheh /* returns 0 if the mw that was removed was already satisfied, -EBUSY 896ccd979bdSMark Fasheh * if the mask still hadn't reached its goal */ 897ccd979bdSMark Fasheh static int lockres_remove_mask_waiter(struct ocfs2_lock_res *lockres, 898ccd979bdSMark Fasheh struct ocfs2_mask_waiter *mw) 899ccd979bdSMark Fasheh { 900ccd979bdSMark Fasheh unsigned long flags; 901ccd979bdSMark Fasheh int ret = 0; 902ccd979bdSMark Fasheh 903ccd979bdSMark Fasheh spin_lock_irqsave(&lockres->l_lock, flags); 904ccd979bdSMark Fasheh if (!list_empty(&mw->mw_item)) { 905ccd979bdSMark Fasheh if ((lockres->l_flags & mw->mw_mask) != mw->mw_goal) 906ccd979bdSMark Fasheh ret = -EBUSY; 907ccd979bdSMark Fasheh 908ccd979bdSMark Fasheh list_del_init(&mw->mw_item); 909ccd979bdSMark Fasheh init_completion(&mw->mw_complete); 910ccd979bdSMark Fasheh } 911ccd979bdSMark Fasheh spin_unlock_irqrestore(&lockres->l_lock, flags); 912ccd979bdSMark Fasheh 913ccd979bdSMark Fasheh return ret; 914ccd979bdSMark Fasheh 915ccd979bdSMark Fasheh } 916ccd979bdSMark Fasheh 917ccd979bdSMark Fasheh static int ocfs2_cluster_lock(struct ocfs2_super *osb, 918ccd979bdSMark Fasheh struct ocfs2_lock_res *lockres, 919ccd979bdSMark Fasheh int level, 920ccd979bdSMark Fasheh int lkm_flags, 921ccd979bdSMark Fasheh int arg_flags) 922ccd979bdSMark Fasheh { 923ccd979bdSMark Fasheh struct ocfs2_mask_waiter mw; 924ccd979bdSMark Fasheh enum dlm_status status; 925ccd979bdSMark Fasheh int wait, catch_signals = !(osb->s_mount_opt & OCFS2_MOUNT_NOINTR); 926ccd979bdSMark Fasheh int ret = 0; /* gcc doesn't realize wait = 1 guarantees ret is set */ 927ccd979bdSMark Fasheh unsigned long flags; 928ccd979bdSMark Fasheh 929ccd979bdSMark Fasheh mlog_entry_void(); 930ccd979bdSMark Fasheh 931ccd979bdSMark Fasheh ocfs2_init_mask_waiter(&mw); 932ccd979bdSMark Fasheh 933ccd979bdSMark Fasheh again: 934ccd979bdSMark Fasheh wait = 0; 935ccd979bdSMark Fasheh 936ccd979bdSMark Fasheh if (catch_signals && signal_pending(current)) { 937ccd979bdSMark Fasheh ret = -ERESTARTSYS; 938ccd979bdSMark Fasheh goto out; 939ccd979bdSMark Fasheh } 940ccd979bdSMark Fasheh 941ccd979bdSMark Fasheh spin_lock_irqsave(&lockres->l_lock, flags); 942ccd979bdSMark Fasheh 943ccd979bdSMark Fasheh mlog_bug_on_msg(lockres->l_flags & OCFS2_LOCK_FREEING, 944ccd979bdSMark Fasheh "Cluster lock called on freeing lockres %s! flags " 945ccd979bdSMark Fasheh "0x%lx\n", lockres->l_name, lockres->l_flags); 946ccd979bdSMark Fasheh 947ccd979bdSMark Fasheh /* We only compare against the currently granted level 948ccd979bdSMark Fasheh * here. If the lock is blocked waiting on a downconvert, 949ccd979bdSMark Fasheh * we'll get caught below. */ 950ccd979bdSMark Fasheh if (lockres->l_flags & OCFS2_LOCK_BUSY && 951ccd979bdSMark Fasheh level > lockres->l_level) { 952ccd979bdSMark Fasheh /* is someone sitting in dlm_lock? If so, wait on 953ccd979bdSMark Fasheh * them. */ 954ccd979bdSMark Fasheh lockres_add_mask_waiter(lockres, &mw, OCFS2_LOCK_BUSY, 0); 955ccd979bdSMark Fasheh wait = 1; 956ccd979bdSMark Fasheh goto unlock; 957ccd979bdSMark Fasheh } 958ccd979bdSMark Fasheh 959ccd979bdSMark Fasheh if (!(lockres->l_flags & OCFS2_LOCK_ATTACHED)) { 960ccd979bdSMark Fasheh /* lock has not been created yet. */ 961ccd979bdSMark Fasheh spin_unlock_irqrestore(&lockres->l_lock, flags); 962ccd979bdSMark Fasheh 963ccd979bdSMark Fasheh ret = ocfs2_lock_create(osb, lockres, LKM_NLMODE, 0); 964ccd979bdSMark Fasheh if (ret < 0) { 965ccd979bdSMark Fasheh mlog_errno(ret); 966ccd979bdSMark Fasheh goto out; 967ccd979bdSMark Fasheh } 968ccd979bdSMark Fasheh goto again; 969ccd979bdSMark Fasheh } 970ccd979bdSMark Fasheh 971ccd979bdSMark Fasheh if (lockres->l_flags & OCFS2_LOCK_BLOCKED && 972ccd979bdSMark Fasheh !ocfs2_may_continue_on_blocked_lock(lockres, level)) { 973ccd979bdSMark Fasheh /* is the lock is currently blocked on behalf of 974ccd979bdSMark Fasheh * another node */ 975ccd979bdSMark Fasheh lockres_add_mask_waiter(lockres, &mw, OCFS2_LOCK_BLOCKED, 0); 976ccd979bdSMark Fasheh wait = 1; 977ccd979bdSMark Fasheh goto unlock; 978ccd979bdSMark Fasheh } 979ccd979bdSMark Fasheh 980ccd979bdSMark Fasheh if (level > lockres->l_level) { 981ccd979bdSMark Fasheh if (lockres->l_action != OCFS2_AST_INVALID) 982ccd979bdSMark Fasheh mlog(ML_ERROR, "lockres %s has action %u pending\n", 983ccd979bdSMark Fasheh lockres->l_name, lockres->l_action); 984ccd979bdSMark Fasheh 985ccd979bdSMark Fasheh lockres->l_action = OCFS2_AST_CONVERT; 986ccd979bdSMark Fasheh lockres->l_requested = level; 987ccd979bdSMark Fasheh lockres_or_flags(lockres, OCFS2_LOCK_BUSY); 988ccd979bdSMark Fasheh spin_unlock_irqrestore(&lockres->l_lock, flags); 989ccd979bdSMark Fasheh 990ccd979bdSMark Fasheh BUG_ON(level == LKM_IVMODE); 991ccd979bdSMark Fasheh BUG_ON(level == LKM_NLMODE); 992ccd979bdSMark Fasheh 993ccd979bdSMark Fasheh mlog(0, "lock %s, convert from %d to level = %d\n", 994ccd979bdSMark Fasheh lockres->l_name, lockres->l_level, level); 995ccd979bdSMark Fasheh 996ccd979bdSMark Fasheh /* call dlm_lock to upgrade lock now */ 997ccd979bdSMark Fasheh status = dlmlock(osb->dlm, 998ccd979bdSMark Fasheh level, 999ccd979bdSMark Fasheh &lockres->l_lksb, 1000ccd979bdSMark Fasheh lkm_flags|LKM_CONVERT|LKM_VALBLK, 1001ccd979bdSMark Fasheh lockres->l_name, 1002ccd979bdSMark Fasheh lockres->l_ops->ast, 1003ccd979bdSMark Fasheh lockres, 1004ccd979bdSMark Fasheh lockres->l_ops->bast); 1005ccd979bdSMark Fasheh if (status != DLM_NORMAL) { 1006ccd979bdSMark Fasheh if ((lkm_flags & LKM_NOQUEUE) && 1007ccd979bdSMark Fasheh (status == DLM_NOTQUEUED)) 1008ccd979bdSMark Fasheh ret = -EAGAIN; 1009ccd979bdSMark Fasheh else { 1010ccd979bdSMark Fasheh ocfs2_log_dlm_error("dlmlock", status, 1011ccd979bdSMark Fasheh lockres); 1012ccd979bdSMark Fasheh ret = -EINVAL; 1013ccd979bdSMark Fasheh } 1014ccd979bdSMark Fasheh ocfs2_recover_from_dlm_error(lockres, 1); 1015ccd979bdSMark Fasheh goto out; 1016ccd979bdSMark Fasheh } 1017ccd979bdSMark Fasheh 1018ccd979bdSMark Fasheh mlog(0, "lock %s, successfull return from dlmlock\n", 1019ccd979bdSMark Fasheh lockres->l_name); 1020ccd979bdSMark Fasheh 1021ccd979bdSMark Fasheh /* At this point we've gone inside the dlm and need to 1022ccd979bdSMark Fasheh * complete our work regardless. */ 1023ccd979bdSMark Fasheh catch_signals = 0; 1024ccd979bdSMark Fasheh 1025ccd979bdSMark Fasheh /* wait for busy to clear and carry on */ 1026ccd979bdSMark Fasheh goto again; 1027ccd979bdSMark Fasheh } 1028ccd979bdSMark Fasheh 1029ccd979bdSMark Fasheh /* Ok, if we get here then we're good to go. */ 1030ccd979bdSMark Fasheh ocfs2_inc_holders(lockres, level); 1031ccd979bdSMark Fasheh 1032ccd979bdSMark Fasheh ret = 0; 1033ccd979bdSMark Fasheh unlock: 1034ccd979bdSMark Fasheh spin_unlock_irqrestore(&lockres->l_lock, flags); 1035ccd979bdSMark Fasheh out: 1036ccd979bdSMark Fasheh /* 1037ccd979bdSMark Fasheh * This is helping work around a lock inversion between the page lock 1038ccd979bdSMark Fasheh * and dlm locks. One path holds the page lock while calling aops 1039ccd979bdSMark Fasheh * which block acquiring dlm locks. The voting thread holds dlm 1040ccd979bdSMark Fasheh * locks while acquiring page locks while down converting data locks. 1041ccd979bdSMark Fasheh * This block is helping an aop path notice the inversion and back 1042ccd979bdSMark Fasheh * off to unlock its page lock before trying the dlm lock again. 1043ccd979bdSMark Fasheh */ 1044ccd979bdSMark Fasheh if (wait && arg_flags & OCFS2_LOCK_NONBLOCK && 1045ccd979bdSMark Fasheh mw.mw_mask & (OCFS2_LOCK_BUSY|OCFS2_LOCK_BLOCKED)) { 1046ccd979bdSMark Fasheh wait = 0; 1047ccd979bdSMark Fasheh if (lockres_remove_mask_waiter(lockres, &mw)) 1048ccd979bdSMark Fasheh ret = -EAGAIN; 1049ccd979bdSMark Fasheh else 1050ccd979bdSMark Fasheh goto again; 1051ccd979bdSMark Fasheh } 1052ccd979bdSMark Fasheh if (wait) { 1053ccd979bdSMark Fasheh ret = ocfs2_wait_for_mask(&mw); 1054ccd979bdSMark Fasheh if (ret == 0) 1055ccd979bdSMark Fasheh goto again; 1056ccd979bdSMark Fasheh mlog_errno(ret); 1057ccd979bdSMark Fasheh } 1058ccd979bdSMark Fasheh 1059ccd979bdSMark Fasheh mlog_exit(ret); 1060ccd979bdSMark Fasheh return ret; 1061ccd979bdSMark Fasheh } 1062ccd979bdSMark Fasheh 1063ccd979bdSMark Fasheh static void ocfs2_cluster_unlock(struct ocfs2_super *osb, 1064ccd979bdSMark Fasheh struct ocfs2_lock_res *lockres, 1065ccd979bdSMark Fasheh int level) 1066ccd979bdSMark Fasheh { 1067ccd979bdSMark Fasheh unsigned long flags; 1068ccd979bdSMark Fasheh 1069ccd979bdSMark Fasheh mlog_entry_void(); 1070ccd979bdSMark Fasheh spin_lock_irqsave(&lockres->l_lock, flags); 1071ccd979bdSMark Fasheh ocfs2_dec_holders(lockres, level); 1072ccd979bdSMark Fasheh ocfs2_vote_on_unlock(osb, lockres); 1073ccd979bdSMark Fasheh spin_unlock_irqrestore(&lockres->l_lock, flags); 1074ccd979bdSMark Fasheh mlog_exit_void(); 1075ccd979bdSMark Fasheh } 1076ccd979bdSMark Fasheh 1077ccd979bdSMark Fasheh static int ocfs2_create_new_inode_lock(struct inode *inode, 1078ccd979bdSMark Fasheh struct ocfs2_lock_res *lockres) 1079ccd979bdSMark Fasheh { 1080ccd979bdSMark Fasheh struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); 1081ccd979bdSMark Fasheh unsigned long flags; 1082ccd979bdSMark Fasheh 1083ccd979bdSMark Fasheh spin_lock_irqsave(&lockres->l_lock, flags); 1084ccd979bdSMark Fasheh BUG_ON(lockres->l_flags & OCFS2_LOCK_ATTACHED); 1085ccd979bdSMark Fasheh lockres_or_flags(lockres, OCFS2_LOCK_LOCAL); 1086ccd979bdSMark Fasheh spin_unlock_irqrestore(&lockres->l_lock, flags); 1087ccd979bdSMark Fasheh 1088ccd979bdSMark Fasheh return ocfs2_lock_create(osb, lockres, LKM_EXMODE, LKM_LOCAL); 1089ccd979bdSMark Fasheh } 1090ccd979bdSMark Fasheh 1091ccd979bdSMark Fasheh /* Grants us an EX lock on the data and metadata resources, skipping 1092ccd979bdSMark Fasheh * the normal cluster directory lookup. Use this ONLY on newly created 1093ccd979bdSMark Fasheh * inodes which other nodes can't possibly see, and which haven't been 1094ccd979bdSMark Fasheh * hashed in the inode hash yet. This can give us a good performance 1095ccd979bdSMark Fasheh * increase as it'll skip the network broadcast normally associated 1096ccd979bdSMark Fasheh * with creating a new lock resource. */ 1097ccd979bdSMark Fasheh int ocfs2_create_new_inode_locks(struct inode *inode) 1098ccd979bdSMark Fasheh { 1099ccd979bdSMark Fasheh int ret; 1100ccd979bdSMark Fasheh 1101ccd979bdSMark Fasheh BUG_ON(!inode); 1102ccd979bdSMark Fasheh BUG_ON(!ocfs2_inode_is_new(inode)); 1103ccd979bdSMark Fasheh 1104ccd979bdSMark Fasheh mlog_entry_void(); 1105ccd979bdSMark Fasheh 1106b0697053SMark Fasheh mlog(0, "Inode %llu\n", (unsigned long long)OCFS2_I(inode)->ip_blkno); 1107ccd979bdSMark Fasheh 1108ccd979bdSMark Fasheh /* NOTE: That we don't increment any of the holder counts, nor 1109ccd979bdSMark Fasheh * do we add anything to a journal handle. Since this is 1110ccd979bdSMark Fasheh * supposed to be a new inode which the cluster doesn't know 1111ccd979bdSMark Fasheh * about yet, there is no need to. As far as the LVB handling 1112ccd979bdSMark Fasheh * is concerned, this is basically like acquiring an EX lock 1113ccd979bdSMark Fasheh * on a resource which has an invalid one -- we'll set it 1114ccd979bdSMark Fasheh * valid when we release the EX. */ 1115ccd979bdSMark Fasheh 1116ccd979bdSMark Fasheh ret = ocfs2_create_new_inode_lock(inode, 1117ccd979bdSMark Fasheh &OCFS2_I(inode)->ip_rw_lockres); 1118ccd979bdSMark Fasheh if (ret) { 1119ccd979bdSMark Fasheh mlog_errno(ret); 1120ccd979bdSMark Fasheh goto bail; 1121ccd979bdSMark Fasheh } 1122ccd979bdSMark Fasheh 1123ccd979bdSMark Fasheh ret = ocfs2_create_new_inode_lock(inode, 1124ccd979bdSMark Fasheh &OCFS2_I(inode)->ip_meta_lockres); 1125ccd979bdSMark Fasheh if (ret) { 1126ccd979bdSMark Fasheh mlog_errno(ret); 1127ccd979bdSMark Fasheh goto bail; 1128ccd979bdSMark Fasheh } 1129ccd979bdSMark Fasheh 1130ccd979bdSMark Fasheh ret = ocfs2_create_new_inode_lock(inode, 1131ccd979bdSMark Fasheh &OCFS2_I(inode)->ip_data_lockres); 1132ccd979bdSMark Fasheh if (ret) { 1133ccd979bdSMark Fasheh mlog_errno(ret); 1134ccd979bdSMark Fasheh goto bail; 1135ccd979bdSMark Fasheh } 1136ccd979bdSMark Fasheh 1137ccd979bdSMark Fasheh bail: 1138ccd979bdSMark Fasheh mlog_exit(ret); 1139ccd979bdSMark Fasheh return ret; 1140ccd979bdSMark Fasheh } 1141ccd979bdSMark Fasheh 1142ccd979bdSMark Fasheh int ocfs2_rw_lock(struct inode *inode, int write) 1143ccd979bdSMark Fasheh { 1144ccd979bdSMark Fasheh int status, level; 1145ccd979bdSMark Fasheh struct ocfs2_lock_res *lockres; 1146ccd979bdSMark Fasheh 1147ccd979bdSMark Fasheh BUG_ON(!inode); 1148ccd979bdSMark Fasheh 1149ccd979bdSMark Fasheh mlog_entry_void(); 1150ccd979bdSMark Fasheh 1151b0697053SMark Fasheh mlog(0, "inode %llu take %s RW lock\n", 1152b0697053SMark Fasheh (unsigned long long)OCFS2_I(inode)->ip_blkno, 1153ccd979bdSMark Fasheh write ? "EXMODE" : "PRMODE"); 1154ccd979bdSMark Fasheh 1155ccd979bdSMark Fasheh lockres = &OCFS2_I(inode)->ip_rw_lockres; 1156ccd979bdSMark Fasheh 1157ccd979bdSMark Fasheh level = write ? LKM_EXMODE : LKM_PRMODE; 1158ccd979bdSMark Fasheh 1159ccd979bdSMark Fasheh status = ocfs2_cluster_lock(OCFS2_SB(inode->i_sb), lockres, level, 0, 1160ccd979bdSMark Fasheh 0); 1161ccd979bdSMark Fasheh if (status < 0) 1162ccd979bdSMark Fasheh mlog_errno(status); 1163ccd979bdSMark Fasheh 1164ccd979bdSMark Fasheh mlog_exit(status); 1165ccd979bdSMark Fasheh return status; 1166ccd979bdSMark Fasheh } 1167ccd979bdSMark Fasheh 1168ccd979bdSMark Fasheh void ocfs2_rw_unlock(struct inode *inode, int write) 1169ccd979bdSMark Fasheh { 1170ccd979bdSMark Fasheh int level = write ? LKM_EXMODE : LKM_PRMODE; 1171ccd979bdSMark Fasheh struct ocfs2_lock_res *lockres = &OCFS2_I(inode)->ip_rw_lockres; 1172ccd979bdSMark Fasheh 1173ccd979bdSMark Fasheh mlog_entry_void(); 1174ccd979bdSMark Fasheh 1175b0697053SMark Fasheh mlog(0, "inode %llu drop %s RW lock\n", 1176b0697053SMark Fasheh (unsigned long long)OCFS2_I(inode)->ip_blkno, 1177ccd979bdSMark Fasheh write ? "EXMODE" : "PRMODE"); 1178ccd979bdSMark Fasheh 1179ccd979bdSMark Fasheh ocfs2_cluster_unlock(OCFS2_SB(inode->i_sb), lockres, level); 1180ccd979bdSMark Fasheh 1181ccd979bdSMark Fasheh mlog_exit_void(); 1182ccd979bdSMark Fasheh } 1183ccd979bdSMark Fasheh 1184ccd979bdSMark Fasheh int ocfs2_data_lock_full(struct inode *inode, 1185ccd979bdSMark Fasheh int write, 1186ccd979bdSMark Fasheh int arg_flags) 1187ccd979bdSMark Fasheh { 1188ccd979bdSMark Fasheh int status = 0, level; 1189ccd979bdSMark Fasheh struct ocfs2_lock_res *lockres; 1190ccd979bdSMark Fasheh 1191ccd979bdSMark Fasheh BUG_ON(!inode); 1192ccd979bdSMark Fasheh 1193ccd979bdSMark Fasheh mlog_entry_void(); 1194ccd979bdSMark Fasheh 1195b0697053SMark Fasheh mlog(0, "inode %llu take %s DATA lock\n", 1196b0697053SMark Fasheh (unsigned long long)OCFS2_I(inode)->ip_blkno, 1197ccd979bdSMark Fasheh write ? "EXMODE" : "PRMODE"); 1198ccd979bdSMark Fasheh 1199ccd979bdSMark Fasheh /* We'll allow faking a readonly data lock for 1200ccd979bdSMark Fasheh * rodevices. */ 1201ccd979bdSMark Fasheh if (ocfs2_is_hard_readonly(OCFS2_SB(inode->i_sb))) { 1202ccd979bdSMark Fasheh if (write) { 1203ccd979bdSMark Fasheh status = -EROFS; 1204ccd979bdSMark Fasheh mlog_errno(status); 1205ccd979bdSMark Fasheh } 1206ccd979bdSMark Fasheh goto out; 1207ccd979bdSMark Fasheh } 1208ccd979bdSMark Fasheh 1209ccd979bdSMark Fasheh lockres = &OCFS2_I(inode)->ip_data_lockres; 1210ccd979bdSMark Fasheh 1211ccd979bdSMark Fasheh level = write ? LKM_EXMODE : LKM_PRMODE; 1212ccd979bdSMark Fasheh 1213ccd979bdSMark Fasheh status = ocfs2_cluster_lock(OCFS2_SB(inode->i_sb), lockres, level, 1214ccd979bdSMark Fasheh 0, arg_flags); 1215ccd979bdSMark Fasheh if (status < 0 && status != -EAGAIN) 1216ccd979bdSMark Fasheh mlog_errno(status); 1217ccd979bdSMark Fasheh 1218ccd979bdSMark Fasheh out: 1219ccd979bdSMark Fasheh mlog_exit(status); 1220ccd979bdSMark Fasheh return status; 1221ccd979bdSMark Fasheh } 1222ccd979bdSMark Fasheh 1223ccd979bdSMark Fasheh /* see ocfs2_meta_lock_with_page() */ 1224ccd979bdSMark Fasheh int ocfs2_data_lock_with_page(struct inode *inode, 1225ccd979bdSMark Fasheh int write, 1226ccd979bdSMark Fasheh struct page *page) 1227ccd979bdSMark Fasheh { 1228ccd979bdSMark Fasheh int ret; 1229ccd979bdSMark Fasheh 1230ccd979bdSMark Fasheh ret = ocfs2_data_lock_full(inode, write, OCFS2_LOCK_NONBLOCK); 1231ccd979bdSMark Fasheh if (ret == -EAGAIN) { 1232ccd979bdSMark Fasheh unlock_page(page); 1233ccd979bdSMark Fasheh if (ocfs2_data_lock(inode, write) == 0) 1234ccd979bdSMark Fasheh ocfs2_data_unlock(inode, write); 1235ccd979bdSMark Fasheh ret = AOP_TRUNCATED_PAGE; 1236ccd979bdSMark Fasheh } 1237ccd979bdSMark Fasheh 1238ccd979bdSMark Fasheh return ret; 1239ccd979bdSMark Fasheh } 1240ccd979bdSMark Fasheh 1241ccd979bdSMark Fasheh static void ocfs2_vote_on_unlock(struct ocfs2_super *osb, 1242ccd979bdSMark Fasheh struct ocfs2_lock_res *lockres) 1243ccd979bdSMark Fasheh { 1244ccd979bdSMark Fasheh int kick = 0; 1245ccd979bdSMark Fasheh 1246ccd979bdSMark Fasheh mlog_entry_void(); 1247ccd979bdSMark Fasheh 1248ccd979bdSMark Fasheh /* If we know that another node is waiting on our lock, kick 1249ccd979bdSMark Fasheh * the vote thread * pre-emptively when we reach a release 1250ccd979bdSMark Fasheh * condition. */ 1251ccd979bdSMark Fasheh if (lockres->l_flags & OCFS2_LOCK_BLOCKED) { 1252ccd979bdSMark Fasheh switch(lockres->l_blocking) { 1253ccd979bdSMark Fasheh case LKM_EXMODE: 1254ccd979bdSMark Fasheh if (!lockres->l_ex_holders && !lockres->l_ro_holders) 1255ccd979bdSMark Fasheh kick = 1; 1256ccd979bdSMark Fasheh break; 1257ccd979bdSMark Fasheh case LKM_PRMODE: 1258ccd979bdSMark Fasheh if (!lockres->l_ex_holders) 1259ccd979bdSMark Fasheh kick = 1; 1260ccd979bdSMark Fasheh break; 1261ccd979bdSMark Fasheh default: 1262ccd979bdSMark Fasheh BUG(); 1263ccd979bdSMark Fasheh } 1264ccd979bdSMark Fasheh } 1265ccd979bdSMark Fasheh 1266ccd979bdSMark Fasheh if (kick) 1267ccd979bdSMark Fasheh ocfs2_kick_vote_thread(osb); 1268ccd979bdSMark Fasheh 1269ccd979bdSMark Fasheh mlog_exit_void(); 1270ccd979bdSMark Fasheh } 1271ccd979bdSMark Fasheh 1272ccd979bdSMark Fasheh void ocfs2_data_unlock(struct inode *inode, 1273ccd979bdSMark Fasheh int write) 1274ccd979bdSMark Fasheh { 1275ccd979bdSMark Fasheh int level = write ? LKM_EXMODE : LKM_PRMODE; 1276ccd979bdSMark Fasheh struct ocfs2_lock_res *lockres = &OCFS2_I(inode)->ip_data_lockres; 1277ccd979bdSMark Fasheh 1278ccd979bdSMark Fasheh mlog_entry_void(); 1279ccd979bdSMark Fasheh 1280b0697053SMark Fasheh mlog(0, "inode %llu drop %s DATA lock\n", 1281b0697053SMark Fasheh (unsigned long long)OCFS2_I(inode)->ip_blkno, 1282ccd979bdSMark Fasheh write ? "EXMODE" : "PRMODE"); 1283ccd979bdSMark Fasheh 1284ccd979bdSMark Fasheh if (!ocfs2_is_hard_readonly(OCFS2_SB(inode->i_sb))) 1285ccd979bdSMark Fasheh ocfs2_cluster_unlock(OCFS2_SB(inode->i_sb), lockres, level); 1286ccd979bdSMark Fasheh 1287ccd979bdSMark Fasheh mlog_exit_void(); 1288ccd979bdSMark Fasheh } 1289ccd979bdSMark Fasheh 1290ccd979bdSMark Fasheh #define OCFS2_SEC_BITS 34 1291ccd979bdSMark Fasheh #define OCFS2_SEC_SHIFT (64 - 34) 1292ccd979bdSMark Fasheh #define OCFS2_NSEC_MASK ((1ULL << OCFS2_SEC_SHIFT) - 1) 1293ccd979bdSMark Fasheh 1294ccd979bdSMark Fasheh /* LVB only has room for 64 bits of time here so we pack it for 1295ccd979bdSMark Fasheh * now. */ 1296ccd979bdSMark Fasheh static u64 ocfs2_pack_timespec(struct timespec *spec) 1297ccd979bdSMark Fasheh { 1298ccd979bdSMark Fasheh u64 res; 1299ccd979bdSMark Fasheh u64 sec = spec->tv_sec; 1300ccd979bdSMark Fasheh u32 nsec = spec->tv_nsec; 1301ccd979bdSMark Fasheh 1302ccd979bdSMark Fasheh res = (sec << OCFS2_SEC_SHIFT) | (nsec & OCFS2_NSEC_MASK); 1303ccd979bdSMark Fasheh 1304ccd979bdSMark Fasheh return res; 1305ccd979bdSMark Fasheh } 1306ccd979bdSMark Fasheh 1307ccd979bdSMark Fasheh /* Call this with the lockres locked. I am reasonably sure we don't 1308ccd979bdSMark Fasheh * need ip_lock in this function as anyone who would be changing those 1309ccd979bdSMark Fasheh * values is supposed to be blocked in ocfs2_meta_lock right now. */ 1310ccd979bdSMark Fasheh static void __ocfs2_stuff_meta_lvb(struct inode *inode) 1311ccd979bdSMark Fasheh { 1312ccd979bdSMark Fasheh struct ocfs2_inode_info *oi = OCFS2_I(inode); 1313ccd979bdSMark Fasheh struct ocfs2_lock_res *lockres = &oi->ip_meta_lockres; 1314ccd979bdSMark Fasheh struct ocfs2_meta_lvb *lvb; 1315ccd979bdSMark Fasheh 1316ccd979bdSMark Fasheh mlog_entry_void(); 1317ccd979bdSMark Fasheh 1318ccd979bdSMark Fasheh lvb = (struct ocfs2_meta_lvb *) lockres->l_lksb.lvb; 1319ccd979bdSMark Fasheh 1320ccd979bdSMark Fasheh lvb->lvb_version = cpu_to_be32(OCFS2_LVB_VERSION); 1321ccd979bdSMark Fasheh lvb->lvb_isize = cpu_to_be64(i_size_read(inode)); 1322ccd979bdSMark Fasheh lvb->lvb_iclusters = cpu_to_be32(oi->ip_clusters); 1323ccd979bdSMark Fasheh lvb->lvb_iuid = cpu_to_be32(inode->i_uid); 1324ccd979bdSMark Fasheh lvb->lvb_igid = cpu_to_be32(inode->i_gid); 1325ccd979bdSMark Fasheh lvb->lvb_imode = cpu_to_be16(inode->i_mode); 1326ccd979bdSMark Fasheh lvb->lvb_inlink = cpu_to_be16(inode->i_nlink); 1327ccd979bdSMark Fasheh lvb->lvb_iatime_packed = 1328ccd979bdSMark Fasheh cpu_to_be64(ocfs2_pack_timespec(&inode->i_atime)); 1329ccd979bdSMark Fasheh lvb->lvb_ictime_packed = 1330ccd979bdSMark Fasheh cpu_to_be64(ocfs2_pack_timespec(&inode->i_ctime)); 1331ccd979bdSMark Fasheh lvb->lvb_imtime_packed = 1332ccd979bdSMark Fasheh cpu_to_be64(ocfs2_pack_timespec(&inode->i_mtime)); 1333ccd979bdSMark Fasheh 1334ccd979bdSMark Fasheh mlog_meta_lvb(0, lockres); 1335ccd979bdSMark Fasheh 1336ccd979bdSMark Fasheh mlog_exit_void(); 1337ccd979bdSMark Fasheh } 1338ccd979bdSMark Fasheh 1339ccd979bdSMark Fasheh static void ocfs2_unpack_timespec(struct timespec *spec, 1340ccd979bdSMark Fasheh u64 packed_time) 1341ccd979bdSMark Fasheh { 1342ccd979bdSMark Fasheh spec->tv_sec = packed_time >> OCFS2_SEC_SHIFT; 1343ccd979bdSMark Fasheh spec->tv_nsec = packed_time & OCFS2_NSEC_MASK; 1344ccd979bdSMark Fasheh } 1345ccd979bdSMark Fasheh 1346ccd979bdSMark Fasheh static void ocfs2_refresh_inode_from_lvb(struct inode *inode) 1347ccd979bdSMark Fasheh { 1348ccd979bdSMark Fasheh struct ocfs2_inode_info *oi = OCFS2_I(inode); 1349ccd979bdSMark Fasheh struct ocfs2_lock_res *lockres = &oi->ip_meta_lockres; 1350ccd979bdSMark Fasheh struct ocfs2_meta_lvb *lvb; 1351ccd979bdSMark Fasheh 1352ccd979bdSMark Fasheh mlog_entry_void(); 1353ccd979bdSMark Fasheh 1354ccd979bdSMark Fasheh mlog_meta_lvb(0, lockres); 1355ccd979bdSMark Fasheh 1356ccd979bdSMark Fasheh lvb = (struct ocfs2_meta_lvb *) lockres->l_lksb.lvb; 1357ccd979bdSMark Fasheh 1358ccd979bdSMark Fasheh /* We're safe here without the lockres lock... */ 1359ccd979bdSMark Fasheh spin_lock(&oi->ip_lock); 1360ccd979bdSMark Fasheh oi->ip_clusters = be32_to_cpu(lvb->lvb_iclusters); 1361ccd979bdSMark Fasheh i_size_write(inode, be64_to_cpu(lvb->lvb_isize)); 1362ccd979bdSMark Fasheh 1363ccd979bdSMark Fasheh /* fast-symlinks are a special case */ 1364ccd979bdSMark Fasheh if (S_ISLNK(inode->i_mode) && !oi->ip_clusters) 1365ccd979bdSMark Fasheh inode->i_blocks = 0; 1366ccd979bdSMark Fasheh else 1367ccd979bdSMark Fasheh inode->i_blocks = 1368ccd979bdSMark Fasheh ocfs2_align_bytes_to_sectors(i_size_read(inode)); 1369ccd979bdSMark Fasheh 1370ccd979bdSMark Fasheh inode->i_uid = be32_to_cpu(lvb->lvb_iuid); 1371ccd979bdSMark Fasheh inode->i_gid = be32_to_cpu(lvb->lvb_igid); 1372ccd979bdSMark Fasheh inode->i_mode = be16_to_cpu(lvb->lvb_imode); 1373ccd979bdSMark Fasheh inode->i_nlink = be16_to_cpu(lvb->lvb_inlink); 1374ccd979bdSMark Fasheh ocfs2_unpack_timespec(&inode->i_atime, 1375ccd979bdSMark Fasheh be64_to_cpu(lvb->lvb_iatime_packed)); 1376ccd979bdSMark Fasheh ocfs2_unpack_timespec(&inode->i_mtime, 1377ccd979bdSMark Fasheh be64_to_cpu(lvb->lvb_imtime_packed)); 1378ccd979bdSMark Fasheh ocfs2_unpack_timespec(&inode->i_ctime, 1379ccd979bdSMark Fasheh be64_to_cpu(lvb->lvb_ictime_packed)); 1380ccd979bdSMark Fasheh spin_unlock(&oi->ip_lock); 1381ccd979bdSMark Fasheh 1382ccd979bdSMark Fasheh mlog_exit_void(); 1383ccd979bdSMark Fasheh } 1384ccd979bdSMark Fasheh 1385ccd979bdSMark Fasheh static inline int ocfs2_meta_lvb_is_trustable(struct ocfs2_lock_res *lockres) 1386ccd979bdSMark Fasheh { 1387ccd979bdSMark Fasheh struct ocfs2_meta_lvb *lvb = (struct ocfs2_meta_lvb *) lockres->l_lksb.lvb; 1388ccd979bdSMark Fasheh 1389ccd979bdSMark Fasheh if (be32_to_cpu(lvb->lvb_version) == OCFS2_LVB_VERSION) 1390ccd979bdSMark Fasheh return 1; 1391ccd979bdSMark Fasheh return 0; 1392ccd979bdSMark Fasheh } 1393ccd979bdSMark Fasheh 1394ccd979bdSMark Fasheh /* Determine whether a lock resource needs to be refreshed, and 1395ccd979bdSMark Fasheh * arbitrate who gets to refresh it. 1396ccd979bdSMark Fasheh * 1397ccd979bdSMark Fasheh * 0 means no refresh needed. 1398ccd979bdSMark Fasheh * 1399ccd979bdSMark Fasheh * > 0 means you need to refresh this and you MUST call 1400ccd979bdSMark Fasheh * ocfs2_complete_lock_res_refresh afterwards. */ 1401ccd979bdSMark Fasheh static int ocfs2_should_refresh_lock_res(struct ocfs2_lock_res *lockres) 1402ccd979bdSMark Fasheh { 1403ccd979bdSMark Fasheh unsigned long flags; 1404ccd979bdSMark Fasheh int status = 0; 1405ccd979bdSMark Fasheh 1406ccd979bdSMark Fasheh mlog_entry_void(); 1407ccd979bdSMark Fasheh 1408ccd979bdSMark Fasheh refresh_check: 1409ccd979bdSMark Fasheh spin_lock_irqsave(&lockres->l_lock, flags); 1410ccd979bdSMark Fasheh if (!(lockres->l_flags & OCFS2_LOCK_NEEDS_REFRESH)) { 1411ccd979bdSMark Fasheh spin_unlock_irqrestore(&lockres->l_lock, flags); 1412ccd979bdSMark Fasheh goto bail; 1413ccd979bdSMark Fasheh } 1414ccd979bdSMark Fasheh 1415ccd979bdSMark Fasheh if (lockres->l_flags & OCFS2_LOCK_REFRESHING) { 1416ccd979bdSMark Fasheh spin_unlock_irqrestore(&lockres->l_lock, flags); 1417ccd979bdSMark Fasheh 1418ccd979bdSMark Fasheh ocfs2_wait_on_refreshing_lock(lockres); 1419ccd979bdSMark Fasheh goto refresh_check; 1420ccd979bdSMark Fasheh } 1421ccd979bdSMark Fasheh 1422ccd979bdSMark Fasheh /* Ok, I'll be the one to refresh this lock. */ 1423ccd979bdSMark Fasheh lockres_or_flags(lockres, OCFS2_LOCK_REFRESHING); 1424ccd979bdSMark Fasheh spin_unlock_irqrestore(&lockres->l_lock, flags); 1425ccd979bdSMark Fasheh 1426ccd979bdSMark Fasheh status = 1; 1427ccd979bdSMark Fasheh bail: 1428ccd979bdSMark Fasheh mlog_exit(status); 1429ccd979bdSMark Fasheh return status; 1430ccd979bdSMark Fasheh } 1431ccd979bdSMark Fasheh 1432ccd979bdSMark Fasheh /* If status is non zero, I'll mark it as not being in refresh 1433ccd979bdSMark Fasheh * anymroe, but i won't clear the needs refresh flag. */ 1434ccd979bdSMark Fasheh static inline void ocfs2_complete_lock_res_refresh(struct ocfs2_lock_res *lockres, 1435ccd979bdSMark Fasheh int status) 1436ccd979bdSMark Fasheh { 1437ccd979bdSMark Fasheh unsigned long flags; 1438ccd979bdSMark Fasheh mlog_entry_void(); 1439ccd979bdSMark Fasheh 1440ccd979bdSMark Fasheh spin_lock_irqsave(&lockres->l_lock, flags); 1441ccd979bdSMark Fasheh lockres_clear_flags(lockres, OCFS2_LOCK_REFRESHING); 1442ccd979bdSMark Fasheh if (!status) 1443ccd979bdSMark Fasheh lockres_clear_flags(lockres, OCFS2_LOCK_NEEDS_REFRESH); 1444ccd979bdSMark Fasheh spin_unlock_irqrestore(&lockres->l_lock, flags); 1445ccd979bdSMark Fasheh 1446ccd979bdSMark Fasheh wake_up(&lockres->l_event); 1447ccd979bdSMark Fasheh 1448ccd979bdSMark Fasheh mlog_exit_void(); 1449ccd979bdSMark Fasheh } 1450ccd979bdSMark Fasheh 1451ccd979bdSMark Fasheh /* may or may not return a bh if it went to disk. */ 1452ccd979bdSMark Fasheh static int ocfs2_meta_lock_update(struct inode *inode, 1453ccd979bdSMark Fasheh struct buffer_head **bh) 1454ccd979bdSMark Fasheh { 1455ccd979bdSMark Fasheh int status = 0; 1456ccd979bdSMark Fasheh struct ocfs2_inode_info *oi = OCFS2_I(inode); 1457ccd979bdSMark Fasheh struct ocfs2_lock_res *lockres; 1458ccd979bdSMark Fasheh struct ocfs2_dinode *fe; 1459ccd979bdSMark Fasheh 1460ccd979bdSMark Fasheh mlog_entry_void(); 1461ccd979bdSMark Fasheh 1462ccd979bdSMark Fasheh spin_lock(&oi->ip_lock); 1463ccd979bdSMark Fasheh if (oi->ip_flags & OCFS2_INODE_DELETED) { 1464b0697053SMark Fasheh mlog(0, "Orphaned inode %llu was deleted while we " 1465ccd979bdSMark Fasheh "were waiting on a lock. ip_flags = 0x%x\n", 1466b0697053SMark Fasheh (unsigned long long)oi->ip_blkno, oi->ip_flags); 1467ccd979bdSMark Fasheh spin_unlock(&oi->ip_lock); 1468ccd979bdSMark Fasheh status = -ENOENT; 1469ccd979bdSMark Fasheh goto bail; 1470ccd979bdSMark Fasheh } 1471ccd979bdSMark Fasheh spin_unlock(&oi->ip_lock); 1472ccd979bdSMark Fasheh 1473ccd979bdSMark Fasheh lockres = &oi->ip_meta_lockres; 1474ccd979bdSMark Fasheh 1475ccd979bdSMark Fasheh if (!ocfs2_should_refresh_lock_res(lockres)) 1476ccd979bdSMark Fasheh goto bail; 1477ccd979bdSMark Fasheh 1478ccd979bdSMark Fasheh /* This will discard any caching information we might have had 1479ccd979bdSMark Fasheh * for the inode metadata. */ 1480ccd979bdSMark Fasheh ocfs2_metadata_cache_purge(inode); 1481ccd979bdSMark Fasheh 1482ccd979bdSMark Fasheh /* will do nothing for inode types that don't use the extent 1483ccd979bdSMark Fasheh * map (directories, bitmap files, etc) */ 1484ccd979bdSMark Fasheh ocfs2_extent_map_trunc(inode, 0); 1485ccd979bdSMark Fasheh 1486ccd979bdSMark Fasheh if (ocfs2_meta_lvb_is_trustable(lockres)) { 1487b0697053SMark Fasheh mlog(0, "Trusting LVB on inode %llu\n", 1488b0697053SMark Fasheh (unsigned long long)oi->ip_blkno); 1489ccd979bdSMark Fasheh ocfs2_refresh_inode_from_lvb(inode); 1490ccd979bdSMark Fasheh } else { 1491ccd979bdSMark Fasheh /* Boo, we have to go to disk. */ 1492ccd979bdSMark Fasheh /* read bh, cast, ocfs2_refresh_inode */ 1493ccd979bdSMark Fasheh status = ocfs2_read_block(OCFS2_SB(inode->i_sb), oi->ip_blkno, 1494ccd979bdSMark Fasheh bh, OCFS2_BH_CACHED, inode); 1495ccd979bdSMark Fasheh if (status < 0) { 1496ccd979bdSMark Fasheh mlog_errno(status); 1497ccd979bdSMark Fasheh goto bail_refresh; 1498ccd979bdSMark Fasheh } 1499ccd979bdSMark Fasheh fe = (struct ocfs2_dinode *) (*bh)->b_data; 1500ccd979bdSMark Fasheh 1501ccd979bdSMark Fasheh /* This is a good chance to make sure we're not 1502ccd979bdSMark Fasheh * locking an invalid object. 1503ccd979bdSMark Fasheh * 1504ccd979bdSMark Fasheh * We bug on a stale inode here because we checked 1505ccd979bdSMark Fasheh * above whether it was wiped from disk. The wiping 1506ccd979bdSMark Fasheh * node provides a guarantee that we receive that 1507ccd979bdSMark Fasheh * message and can mark the inode before dropping any 1508ccd979bdSMark Fasheh * locks associated with it. */ 1509ccd979bdSMark Fasheh if (!OCFS2_IS_VALID_DINODE(fe)) { 1510ccd979bdSMark Fasheh OCFS2_RO_ON_INVALID_DINODE(inode->i_sb, fe); 1511ccd979bdSMark Fasheh status = -EIO; 1512ccd979bdSMark Fasheh goto bail_refresh; 1513ccd979bdSMark Fasheh } 1514ccd979bdSMark Fasheh mlog_bug_on_msg(inode->i_generation != 1515ccd979bdSMark Fasheh le32_to_cpu(fe->i_generation), 1516b0697053SMark Fasheh "Invalid dinode %llu disk generation: %u " 1517ccd979bdSMark Fasheh "inode->i_generation: %u\n", 1518b0697053SMark Fasheh (unsigned long long)oi->ip_blkno, 1519b0697053SMark Fasheh le32_to_cpu(fe->i_generation), 1520ccd979bdSMark Fasheh inode->i_generation); 1521ccd979bdSMark Fasheh mlog_bug_on_msg(le64_to_cpu(fe->i_dtime) || 1522ccd979bdSMark Fasheh !(fe->i_flags & cpu_to_le32(OCFS2_VALID_FL)), 1523b0697053SMark Fasheh "Stale dinode %llu dtime: %llu flags: 0x%x\n", 1524b0697053SMark Fasheh (unsigned long long)oi->ip_blkno, 1525b0697053SMark Fasheh (unsigned long long)le64_to_cpu(fe->i_dtime), 1526ccd979bdSMark Fasheh le32_to_cpu(fe->i_flags)); 1527ccd979bdSMark Fasheh 1528ccd979bdSMark Fasheh ocfs2_refresh_inode(inode, fe); 1529ccd979bdSMark Fasheh } 1530ccd979bdSMark Fasheh 1531ccd979bdSMark Fasheh status = 0; 1532ccd979bdSMark Fasheh bail_refresh: 1533ccd979bdSMark Fasheh ocfs2_complete_lock_res_refresh(lockres, status); 1534ccd979bdSMark Fasheh bail: 1535ccd979bdSMark Fasheh mlog_exit(status); 1536ccd979bdSMark Fasheh return status; 1537ccd979bdSMark Fasheh } 1538ccd979bdSMark Fasheh 1539ccd979bdSMark Fasheh static int ocfs2_assign_bh(struct inode *inode, 1540ccd979bdSMark Fasheh struct buffer_head **ret_bh, 1541ccd979bdSMark Fasheh struct buffer_head *passed_bh) 1542ccd979bdSMark Fasheh { 1543ccd979bdSMark Fasheh int status; 1544ccd979bdSMark Fasheh 1545ccd979bdSMark Fasheh if (passed_bh) { 1546ccd979bdSMark Fasheh /* Ok, the update went to disk for us, use the 1547ccd979bdSMark Fasheh * returned bh. */ 1548ccd979bdSMark Fasheh *ret_bh = passed_bh; 1549ccd979bdSMark Fasheh get_bh(*ret_bh); 1550ccd979bdSMark Fasheh 1551ccd979bdSMark Fasheh return 0; 1552ccd979bdSMark Fasheh } 1553ccd979bdSMark Fasheh 1554ccd979bdSMark Fasheh status = ocfs2_read_block(OCFS2_SB(inode->i_sb), 1555ccd979bdSMark Fasheh OCFS2_I(inode)->ip_blkno, 1556ccd979bdSMark Fasheh ret_bh, 1557ccd979bdSMark Fasheh OCFS2_BH_CACHED, 1558ccd979bdSMark Fasheh inode); 1559ccd979bdSMark Fasheh if (status < 0) 1560ccd979bdSMark Fasheh mlog_errno(status); 1561ccd979bdSMark Fasheh 1562ccd979bdSMark Fasheh return status; 1563ccd979bdSMark Fasheh } 1564ccd979bdSMark Fasheh 1565ccd979bdSMark Fasheh /* 1566ccd979bdSMark Fasheh * returns < 0 error if the callback will never be called, otherwise 1567ccd979bdSMark Fasheh * the result of the lock will be communicated via the callback. 1568ccd979bdSMark Fasheh */ 1569ccd979bdSMark Fasheh int ocfs2_meta_lock_full(struct inode *inode, 1570ccd979bdSMark Fasheh struct ocfs2_journal_handle *handle, 1571ccd979bdSMark Fasheh struct buffer_head **ret_bh, 1572ccd979bdSMark Fasheh int ex, 1573ccd979bdSMark Fasheh int arg_flags) 1574ccd979bdSMark Fasheh { 1575ccd979bdSMark Fasheh int status, level, dlm_flags, acquired; 1576ccd979bdSMark Fasheh struct ocfs2_lock_res *lockres; 1577ccd979bdSMark Fasheh struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); 1578ccd979bdSMark Fasheh struct buffer_head *local_bh = NULL; 1579ccd979bdSMark Fasheh 1580ccd979bdSMark Fasheh BUG_ON(!inode); 1581ccd979bdSMark Fasheh 1582ccd979bdSMark Fasheh mlog_entry_void(); 1583ccd979bdSMark Fasheh 1584b0697053SMark Fasheh mlog(0, "inode %llu, take %s META lock\n", 1585b0697053SMark Fasheh (unsigned long long)OCFS2_I(inode)->ip_blkno, 1586ccd979bdSMark Fasheh ex ? "EXMODE" : "PRMODE"); 1587ccd979bdSMark Fasheh 1588ccd979bdSMark Fasheh status = 0; 1589ccd979bdSMark Fasheh acquired = 0; 1590ccd979bdSMark Fasheh /* We'll allow faking a readonly metadata lock for 1591ccd979bdSMark Fasheh * rodevices. */ 1592ccd979bdSMark Fasheh if (ocfs2_is_hard_readonly(osb)) { 1593ccd979bdSMark Fasheh if (ex) 1594ccd979bdSMark Fasheh status = -EROFS; 1595ccd979bdSMark Fasheh goto bail; 1596ccd979bdSMark Fasheh } 1597ccd979bdSMark Fasheh 1598ccd979bdSMark Fasheh if (!(arg_flags & OCFS2_META_LOCK_RECOVERY)) 1599ccd979bdSMark Fasheh wait_event(osb->recovery_event, 1600ccd979bdSMark Fasheh ocfs2_node_map_is_empty(osb, &osb->recovery_map)); 1601ccd979bdSMark Fasheh 1602ccd979bdSMark Fasheh acquired = 0; 1603ccd979bdSMark Fasheh lockres = &OCFS2_I(inode)->ip_meta_lockres; 1604ccd979bdSMark Fasheh level = ex ? LKM_EXMODE : LKM_PRMODE; 1605ccd979bdSMark Fasheh dlm_flags = 0; 1606ccd979bdSMark Fasheh if (arg_flags & OCFS2_META_LOCK_NOQUEUE) 1607ccd979bdSMark Fasheh dlm_flags |= LKM_NOQUEUE; 1608ccd979bdSMark Fasheh 1609ccd979bdSMark Fasheh status = ocfs2_cluster_lock(osb, lockres, level, dlm_flags, arg_flags); 1610ccd979bdSMark Fasheh if (status < 0) { 1611ccd979bdSMark Fasheh if (status != -EAGAIN && status != -EIOCBRETRY) 1612ccd979bdSMark Fasheh mlog_errno(status); 1613ccd979bdSMark Fasheh goto bail; 1614ccd979bdSMark Fasheh } 1615ccd979bdSMark Fasheh 1616ccd979bdSMark Fasheh /* Notify the error cleanup path to drop the cluster lock. */ 1617ccd979bdSMark Fasheh acquired = 1; 1618ccd979bdSMark Fasheh 1619ccd979bdSMark Fasheh /* We wait twice because a node may have died while we were in 1620ccd979bdSMark Fasheh * the lower dlm layers. The second time though, we've 1621ccd979bdSMark Fasheh * committed to owning this lock so we don't allow signals to 1622ccd979bdSMark Fasheh * abort the operation. */ 1623ccd979bdSMark Fasheh if (!(arg_flags & OCFS2_META_LOCK_RECOVERY)) 1624ccd979bdSMark Fasheh wait_event(osb->recovery_event, 1625ccd979bdSMark Fasheh ocfs2_node_map_is_empty(osb, &osb->recovery_map)); 1626ccd979bdSMark Fasheh 1627ccd979bdSMark Fasheh /* This is fun. The caller may want a bh back, or it may 1628ccd979bdSMark Fasheh * not. ocfs2_meta_lock_update definitely wants one in, but 1629ccd979bdSMark Fasheh * may or may not read one, depending on what's in the 1630ccd979bdSMark Fasheh * LVB. The result of all of this is that we've *only* gone to 1631ccd979bdSMark Fasheh * disk if we have to, so the complexity is worthwhile. */ 1632ccd979bdSMark Fasheh status = ocfs2_meta_lock_update(inode, &local_bh); 1633ccd979bdSMark Fasheh if (status < 0) { 1634ccd979bdSMark Fasheh if (status != -ENOENT) 1635ccd979bdSMark Fasheh mlog_errno(status); 1636ccd979bdSMark Fasheh goto bail; 1637ccd979bdSMark Fasheh } 1638ccd979bdSMark Fasheh 1639ccd979bdSMark Fasheh if (ret_bh) { 1640ccd979bdSMark Fasheh status = ocfs2_assign_bh(inode, ret_bh, local_bh); 1641ccd979bdSMark Fasheh if (status < 0) { 1642ccd979bdSMark Fasheh mlog_errno(status); 1643ccd979bdSMark Fasheh goto bail; 1644ccd979bdSMark Fasheh } 1645ccd979bdSMark Fasheh } 1646ccd979bdSMark Fasheh 1647ccd979bdSMark Fasheh if (handle) { 1648ccd979bdSMark Fasheh status = ocfs2_handle_add_lock(handle, inode); 1649ccd979bdSMark Fasheh if (status < 0) 1650ccd979bdSMark Fasheh mlog_errno(status); 1651ccd979bdSMark Fasheh } 1652ccd979bdSMark Fasheh 1653ccd979bdSMark Fasheh bail: 1654ccd979bdSMark Fasheh if (status < 0) { 1655ccd979bdSMark Fasheh if (ret_bh && (*ret_bh)) { 1656ccd979bdSMark Fasheh brelse(*ret_bh); 1657ccd979bdSMark Fasheh *ret_bh = NULL; 1658ccd979bdSMark Fasheh } 1659ccd979bdSMark Fasheh if (acquired) 1660ccd979bdSMark Fasheh ocfs2_meta_unlock(inode, ex); 1661ccd979bdSMark Fasheh } 1662ccd979bdSMark Fasheh 1663ccd979bdSMark Fasheh if (local_bh) 1664ccd979bdSMark Fasheh brelse(local_bh); 1665ccd979bdSMark Fasheh 1666ccd979bdSMark Fasheh mlog_exit(status); 1667ccd979bdSMark Fasheh return status; 1668ccd979bdSMark Fasheh } 1669ccd979bdSMark Fasheh 1670ccd979bdSMark Fasheh /* 1671ccd979bdSMark Fasheh * This is working around a lock inversion between tasks acquiring DLM locks 1672ccd979bdSMark Fasheh * while holding a page lock and the vote thread which blocks dlm lock acquiry 1673ccd979bdSMark Fasheh * while acquiring page locks. 1674ccd979bdSMark Fasheh * 1675ccd979bdSMark Fasheh * ** These _with_page variantes are only intended to be called from aop 1676ccd979bdSMark Fasheh * methods that hold page locks and return a very specific *positive* error 1677ccd979bdSMark Fasheh * code that aop methods pass up to the VFS -- test for errors with != 0. ** 1678ccd979bdSMark Fasheh * 1679ccd979bdSMark Fasheh * The DLM is called such that it returns -EAGAIN if it would have blocked 1680ccd979bdSMark Fasheh * waiting for the vote thread. In that case we unlock our page so the vote 1681ccd979bdSMark Fasheh * thread can make progress. Once we've done this we have to return 1682ccd979bdSMark Fasheh * AOP_TRUNCATED_PAGE so the aop method that called us can bubble that back up 1683ccd979bdSMark Fasheh * into the VFS who will then immediately retry the aop call. 1684ccd979bdSMark Fasheh * 1685ccd979bdSMark Fasheh * We do a blocking lock and immediate unlock before returning, though, so that 1686ccd979bdSMark Fasheh * the lock has a great chance of being cached on this node by the time the VFS 1687ccd979bdSMark Fasheh * calls back to retry the aop. This has a potential to livelock as nodes 1688ccd979bdSMark Fasheh * ping locks back and forth, but that's a risk we're willing to take to avoid 1689ccd979bdSMark Fasheh * the lock inversion simply. 1690ccd979bdSMark Fasheh */ 1691ccd979bdSMark Fasheh int ocfs2_meta_lock_with_page(struct inode *inode, 1692ccd979bdSMark Fasheh struct ocfs2_journal_handle *handle, 1693ccd979bdSMark Fasheh struct buffer_head **ret_bh, 1694ccd979bdSMark Fasheh int ex, 1695ccd979bdSMark Fasheh struct page *page) 1696ccd979bdSMark Fasheh { 1697ccd979bdSMark Fasheh int ret; 1698ccd979bdSMark Fasheh 1699ccd979bdSMark Fasheh ret = ocfs2_meta_lock_full(inode, handle, ret_bh, ex, 1700ccd979bdSMark Fasheh OCFS2_LOCK_NONBLOCK); 1701ccd979bdSMark Fasheh if (ret == -EAGAIN) { 1702ccd979bdSMark Fasheh unlock_page(page); 1703ccd979bdSMark Fasheh if (ocfs2_meta_lock(inode, handle, ret_bh, ex) == 0) 1704ccd979bdSMark Fasheh ocfs2_meta_unlock(inode, ex); 1705ccd979bdSMark Fasheh ret = AOP_TRUNCATED_PAGE; 1706ccd979bdSMark Fasheh } 1707ccd979bdSMark Fasheh 1708ccd979bdSMark Fasheh return ret; 1709ccd979bdSMark Fasheh } 1710ccd979bdSMark Fasheh 1711ccd979bdSMark Fasheh void ocfs2_meta_unlock(struct inode *inode, 1712ccd979bdSMark Fasheh int ex) 1713ccd979bdSMark Fasheh { 1714ccd979bdSMark Fasheh int level = ex ? LKM_EXMODE : LKM_PRMODE; 1715ccd979bdSMark Fasheh struct ocfs2_lock_res *lockres = &OCFS2_I(inode)->ip_meta_lockres; 1716ccd979bdSMark Fasheh 1717ccd979bdSMark Fasheh mlog_entry_void(); 1718ccd979bdSMark Fasheh 1719b0697053SMark Fasheh mlog(0, "inode %llu drop %s META lock\n", 1720b0697053SMark Fasheh (unsigned long long)OCFS2_I(inode)->ip_blkno, 1721ccd979bdSMark Fasheh ex ? "EXMODE" : "PRMODE"); 1722ccd979bdSMark Fasheh 1723ccd979bdSMark Fasheh if (!ocfs2_is_hard_readonly(OCFS2_SB(inode->i_sb))) 1724ccd979bdSMark Fasheh ocfs2_cluster_unlock(OCFS2_SB(inode->i_sb), lockres, level); 1725ccd979bdSMark Fasheh 1726ccd979bdSMark Fasheh mlog_exit_void(); 1727ccd979bdSMark Fasheh } 1728ccd979bdSMark Fasheh 1729ccd979bdSMark Fasheh int ocfs2_super_lock(struct ocfs2_super *osb, 1730ccd979bdSMark Fasheh int ex) 1731ccd979bdSMark Fasheh { 1732ccd979bdSMark Fasheh int status; 1733ccd979bdSMark Fasheh int level = ex ? LKM_EXMODE : LKM_PRMODE; 1734ccd979bdSMark Fasheh struct ocfs2_lock_res *lockres = &osb->osb_super_lockres; 1735ccd979bdSMark Fasheh struct buffer_head *bh; 1736ccd979bdSMark Fasheh struct ocfs2_slot_info *si = osb->slot_info; 1737ccd979bdSMark Fasheh 1738ccd979bdSMark Fasheh mlog_entry_void(); 1739ccd979bdSMark Fasheh 1740ccd979bdSMark Fasheh if (ocfs2_is_hard_readonly(osb)) 1741ccd979bdSMark Fasheh return -EROFS; 1742ccd979bdSMark Fasheh 1743ccd979bdSMark Fasheh status = ocfs2_cluster_lock(osb, lockres, level, 0, 0); 1744ccd979bdSMark Fasheh if (status < 0) { 1745ccd979bdSMark Fasheh mlog_errno(status); 1746ccd979bdSMark Fasheh goto bail; 1747ccd979bdSMark Fasheh } 1748ccd979bdSMark Fasheh 1749ccd979bdSMark Fasheh /* The super block lock path is really in the best position to 1750ccd979bdSMark Fasheh * know when resources covered by the lock need to be 1751ccd979bdSMark Fasheh * refreshed, so we do it here. Of course, making sense of 1752ccd979bdSMark Fasheh * everything is up to the caller :) */ 1753ccd979bdSMark Fasheh status = ocfs2_should_refresh_lock_res(lockres); 1754ccd979bdSMark Fasheh if (status < 0) { 1755ccd979bdSMark Fasheh mlog_errno(status); 1756ccd979bdSMark Fasheh goto bail; 1757ccd979bdSMark Fasheh } 1758ccd979bdSMark Fasheh if (status) { 1759ccd979bdSMark Fasheh bh = si->si_bh; 1760ccd979bdSMark Fasheh status = ocfs2_read_block(osb, bh->b_blocknr, &bh, 0, 1761ccd979bdSMark Fasheh si->si_inode); 1762ccd979bdSMark Fasheh if (status == 0) 1763ccd979bdSMark Fasheh ocfs2_update_slot_info(si); 1764ccd979bdSMark Fasheh 1765ccd979bdSMark Fasheh ocfs2_complete_lock_res_refresh(lockres, status); 1766ccd979bdSMark Fasheh 1767ccd979bdSMark Fasheh if (status < 0) 1768ccd979bdSMark Fasheh mlog_errno(status); 1769ccd979bdSMark Fasheh } 1770ccd979bdSMark Fasheh bail: 1771ccd979bdSMark Fasheh mlog_exit(status); 1772ccd979bdSMark Fasheh return status; 1773ccd979bdSMark Fasheh } 1774ccd979bdSMark Fasheh 1775ccd979bdSMark Fasheh void ocfs2_super_unlock(struct ocfs2_super *osb, 1776ccd979bdSMark Fasheh int ex) 1777ccd979bdSMark Fasheh { 1778ccd979bdSMark Fasheh int level = ex ? LKM_EXMODE : LKM_PRMODE; 1779ccd979bdSMark Fasheh struct ocfs2_lock_res *lockres = &osb->osb_super_lockres; 1780ccd979bdSMark Fasheh 1781ccd979bdSMark Fasheh ocfs2_cluster_unlock(osb, lockres, level); 1782ccd979bdSMark Fasheh } 1783ccd979bdSMark Fasheh 1784ccd979bdSMark Fasheh int ocfs2_rename_lock(struct ocfs2_super *osb) 1785ccd979bdSMark Fasheh { 1786ccd979bdSMark Fasheh int status; 1787ccd979bdSMark Fasheh struct ocfs2_lock_res *lockres = &osb->osb_rename_lockres; 1788ccd979bdSMark Fasheh 1789ccd979bdSMark Fasheh if (ocfs2_is_hard_readonly(osb)) 1790ccd979bdSMark Fasheh return -EROFS; 1791ccd979bdSMark Fasheh 1792ccd979bdSMark Fasheh status = ocfs2_cluster_lock(osb, lockres, LKM_EXMODE, 0, 0); 1793ccd979bdSMark Fasheh if (status < 0) 1794ccd979bdSMark Fasheh mlog_errno(status); 1795ccd979bdSMark Fasheh 1796ccd979bdSMark Fasheh return status; 1797ccd979bdSMark Fasheh } 1798ccd979bdSMark Fasheh 1799ccd979bdSMark Fasheh void ocfs2_rename_unlock(struct ocfs2_super *osb) 1800ccd979bdSMark Fasheh { 1801ccd979bdSMark Fasheh struct ocfs2_lock_res *lockres = &osb->osb_rename_lockres; 1802ccd979bdSMark Fasheh 1803ccd979bdSMark Fasheh ocfs2_cluster_unlock(osb, lockres, LKM_EXMODE); 1804ccd979bdSMark Fasheh } 1805ccd979bdSMark Fasheh 1806ccd979bdSMark Fasheh /* Reference counting of the dlm debug structure. We want this because 1807ccd979bdSMark Fasheh * open references on the debug inodes can live on after a mount, so 1808ccd979bdSMark Fasheh * we can't rely on the ocfs2_super to always exist. */ 1809ccd979bdSMark Fasheh static void ocfs2_dlm_debug_free(struct kref *kref) 1810ccd979bdSMark Fasheh { 1811ccd979bdSMark Fasheh struct ocfs2_dlm_debug *dlm_debug; 1812ccd979bdSMark Fasheh 1813ccd979bdSMark Fasheh dlm_debug = container_of(kref, struct ocfs2_dlm_debug, d_refcnt); 1814ccd979bdSMark Fasheh 1815ccd979bdSMark Fasheh kfree(dlm_debug); 1816ccd979bdSMark Fasheh } 1817ccd979bdSMark Fasheh 1818ccd979bdSMark Fasheh void ocfs2_put_dlm_debug(struct ocfs2_dlm_debug *dlm_debug) 1819ccd979bdSMark Fasheh { 1820ccd979bdSMark Fasheh if (dlm_debug) 1821ccd979bdSMark Fasheh kref_put(&dlm_debug->d_refcnt, ocfs2_dlm_debug_free); 1822ccd979bdSMark Fasheh } 1823ccd979bdSMark Fasheh 1824ccd979bdSMark Fasheh static void ocfs2_get_dlm_debug(struct ocfs2_dlm_debug *debug) 1825ccd979bdSMark Fasheh { 1826ccd979bdSMark Fasheh kref_get(&debug->d_refcnt); 1827ccd979bdSMark Fasheh } 1828ccd979bdSMark Fasheh 1829ccd979bdSMark Fasheh struct ocfs2_dlm_debug *ocfs2_new_dlm_debug(void) 1830ccd979bdSMark Fasheh { 1831ccd979bdSMark Fasheh struct ocfs2_dlm_debug *dlm_debug; 1832ccd979bdSMark Fasheh 1833ccd979bdSMark Fasheh dlm_debug = kmalloc(sizeof(struct ocfs2_dlm_debug), GFP_KERNEL); 1834ccd979bdSMark Fasheh if (!dlm_debug) { 1835ccd979bdSMark Fasheh mlog_errno(-ENOMEM); 1836ccd979bdSMark Fasheh goto out; 1837ccd979bdSMark Fasheh } 1838ccd979bdSMark Fasheh 1839ccd979bdSMark Fasheh kref_init(&dlm_debug->d_refcnt); 1840ccd979bdSMark Fasheh INIT_LIST_HEAD(&dlm_debug->d_lockres_tracking); 1841ccd979bdSMark Fasheh dlm_debug->d_locking_state = NULL; 1842ccd979bdSMark Fasheh out: 1843ccd979bdSMark Fasheh return dlm_debug; 1844ccd979bdSMark Fasheh } 1845ccd979bdSMark Fasheh 1846ccd979bdSMark Fasheh /* Access to this is arbitrated for us via seq_file->sem. */ 1847ccd979bdSMark Fasheh struct ocfs2_dlm_seq_priv { 1848ccd979bdSMark Fasheh struct ocfs2_dlm_debug *p_dlm_debug; 1849ccd979bdSMark Fasheh struct ocfs2_lock_res p_iter_res; 1850ccd979bdSMark Fasheh struct ocfs2_lock_res p_tmp_res; 1851ccd979bdSMark Fasheh }; 1852ccd979bdSMark Fasheh 1853ccd979bdSMark Fasheh static struct ocfs2_lock_res *ocfs2_dlm_next_res(struct ocfs2_lock_res *start, 1854ccd979bdSMark Fasheh struct ocfs2_dlm_seq_priv *priv) 1855ccd979bdSMark Fasheh { 1856ccd979bdSMark Fasheh struct ocfs2_lock_res *iter, *ret = NULL; 1857ccd979bdSMark Fasheh struct ocfs2_dlm_debug *dlm_debug = priv->p_dlm_debug; 1858ccd979bdSMark Fasheh 1859ccd979bdSMark Fasheh assert_spin_locked(&ocfs2_dlm_tracking_lock); 1860ccd979bdSMark Fasheh 1861ccd979bdSMark Fasheh list_for_each_entry(iter, &start->l_debug_list, l_debug_list) { 1862ccd979bdSMark Fasheh /* discover the head of the list */ 1863ccd979bdSMark Fasheh if (&iter->l_debug_list == &dlm_debug->d_lockres_tracking) { 1864ccd979bdSMark Fasheh mlog(0, "End of list found, %p\n", ret); 1865ccd979bdSMark Fasheh break; 1866ccd979bdSMark Fasheh } 1867ccd979bdSMark Fasheh 1868ccd979bdSMark Fasheh /* We track our "dummy" iteration lockres' by a NULL 1869ccd979bdSMark Fasheh * l_ops field. */ 1870ccd979bdSMark Fasheh if (iter->l_ops != NULL) { 1871ccd979bdSMark Fasheh ret = iter; 1872ccd979bdSMark Fasheh break; 1873ccd979bdSMark Fasheh } 1874ccd979bdSMark Fasheh } 1875ccd979bdSMark Fasheh 1876ccd979bdSMark Fasheh return ret; 1877ccd979bdSMark Fasheh } 1878ccd979bdSMark Fasheh 1879ccd979bdSMark Fasheh static void *ocfs2_dlm_seq_start(struct seq_file *m, loff_t *pos) 1880ccd979bdSMark Fasheh { 1881ccd979bdSMark Fasheh struct ocfs2_dlm_seq_priv *priv = m->private; 1882ccd979bdSMark Fasheh struct ocfs2_lock_res *iter; 1883ccd979bdSMark Fasheh 1884ccd979bdSMark Fasheh spin_lock(&ocfs2_dlm_tracking_lock); 1885ccd979bdSMark Fasheh iter = ocfs2_dlm_next_res(&priv->p_iter_res, priv); 1886ccd979bdSMark Fasheh if (iter) { 1887ccd979bdSMark Fasheh /* Since lockres' have the lifetime of their container 1888ccd979bdSMark Fasheh * (which can be inodes, ocfs2_supers, etc) we want to 1889ccd979bdSMark Fasheh * copy this out to a temporary lockres while still 1890ccd979bdSMark Fasheh * under the spinlock. Obviously after this we can't 1891ccd979bdSMark Fasheh * trust any pointers on the copy returned, but that's 1892ccd979bdSMark Fasheh * ok as the information we want isn't typically held 1893ccd979bdSMark Fasheh * in them. */ 1894ccd979bdSMark Fasheh priv->p_tmp_res = *iter; 1895ccd979bdSMark Fasheh iter = &priv->p_tmp_res; 1896ccd979bdSMark Fasheh } 1897ccd979bdSMark Fasheh spin_unlock(&ocfs2_dlm_tracking_lock); 1898ccd979bdSMark Fasheh 1899ccd979bdSMark Fasheh return iter; 1900ccd979bdSMark Fasheh } 1901ccd979bdSMark Fasheh 1902ccd979bdSMark Fasheh static void ocfs2_dlm_seq_stop(struct seq_file *m, void *v) 1903ccd979bdSMark Fasheh { 1904ccd979bdSMark Fasheh } 1905ccd979bdSMark Fasheh 1906ccd979bdSMark Fasheh static void *ocfs2_dlm_seq_next(struct seq_file *m, void *v, loff_t *pos) 1907ccd979bdSMark Fasheh { 1908ccd979bdSMark Fasheh struct ocfs2_dlm_seq_priv *priv = m->private; 1909ccd979bdSMark Fasheh struct ocfs2_lock_res *iter = v; 1910ccd979bdSMark Fasheh struct ocfs2_lock_res *dummy = &priv->p_iter_res; 1911ccd979bdSMark Fasheh 1912ccd979bdSMark Fasheh spin_lock(&ocfs2_dlm_tracking_lock); 1913ccd979bdSMark Fasheh iter = ocfs2_dlm_next_res(iter, priv); 1914ccd979bdSMark Fasheh list_del_init(&dummy->l_debug_list); 1915ccd979bdSMark Fasheh if (iter) { 1916ccd979bdSMark Fasheh list_add(&dummy->l_debug_list, &iter->l_debug_list); 1917ccd979bdSMark Fasheh priv->p_tmp_res = *iter; 1918ccd979bdSMark Fasheh iter = &priv->p_tmp_res; 1919ccd979bdSMark Fasheh } 1920ccd979bdSMark Fasheh spin_unlock(&ocfs2_dlm_tracking_lock); 1921ccd979bdSMark Fasheh 1922ccd979bdSMark Fasheh return iter; 1923ccd979bdSMark Fasheh } 1924ccd979bdSMark Fasheh 1925ccd979bdSMark Fasheh /* So that debugfs.ocfs2 can determine which format is being used */ 1926ccd979bdSMark Fasheh #define OCFS2_DLM_DEBUG_STR_VERSION 1 1927ccd979bdSMark Fasheh static int ocfs2_dlm_seq_show(struct seq_file *m, void *v) 1928ccd979bdSMark Fasheh { 1929ccd979bdSMark Fasheh int i; 1930ccd979bdSMark Fasheh char *lvb; 1931ccd979bdSMark Fasheh struct ocfs2_lock_res *lockres = v; 1932ccd979bdSMark Fasheh 1933ccd979bdSMark Fasheh if (!lockres) 1934ccd979bdSMark Fasheh return -EINVAL; 1935ccd979bdSMark Fasheh 1936ccd979bdSMark Fasheh seq_printf(m, "0x%x\t" 1937ccd979bdSMark Fasheh "%.*s\t" 1938ccd979bdSMark Fasheh "%d\t" 1939ccd979bdSMark Fasheh "0x%lx\t" 1940ccd979bdSMark Fasheh "0x%x\t" 1941ccd979bdSMark Fasheh "0x%x\t" 1942ccd979bdSMark Fasheh "%u\t" 1943ccd979bdSMark Fasheh "%u\t" 1944ccd979bdSMark Fasheh "%d\t" 1945ccd979bdSMark Fasheh "%d\t", 1946ccd979bdSMark Fasheh OCFS2_DLM_DEBUG_STR_VERSION, 1947ccd979bdSMark Fasheh OCFS2_LOCK_ID_MAX_LEN, lockres->l_name, 1948ccd979bdSMark Fasheh lockres->l_level, 1949ccd979bdSMark Fasheh lockres->l_flags, 1950ccd979bdSMark Fasheh lockres->l_action, 1951ccd979bdSMark Fasheh lockres->l_unlock_action, 1952ccd979bdSMark Fasheh lockres->l_ro_holders, 1953ccd979bdSMark Fasheh lockres->l_ex_holders, 1954ccd979bdSMark Fasheh lockres->l_requested, 1955ccd979bdSMark Fasheh lockres->l_blocking); 1956ccd979bdSMark Fasheh 1957ccd979bdSMark Fasheh /* Dump the raw LVB */ 1958ccd979bdSMark Fasheh lvb = lockres->l_lksb.lvb; 1959ccd979bdSMark Fasheh for(i = 0; i < DLM_LVB_LEN; i++) 1960ccd979bdSMark Fasheh seq_printf(m, "0x%x\t", lvb[i]); 1961ccd979bdSMark Fasheh 1962ccd979bdSMark Fasheh /* End the line */ 1963ccd979bdSMark Fasheh seq_printf(m, "\n"); 1964ccd979bdSMark Fasheh return 0; 1965ccd979bdSMark Fasheh } 1966ccd979bdSMark Fasheh 1967ccd979bdSMark Fasheh static struct seq_operations ocfs2_dlm_seq_ops = { 1968ccd979bdSMark Fasheh .start = ocfs2_dlm_seq_start, 1969ccd979bdSMark Fasheh .stop = ocfs2_dlm_seq_stop, 1970ccd979bdSMark Fasheh .next = ocfs2_dlm_seq_next, 1971ccd979bdSMark Fasheh .show = ocfs2_dlm_seq_show, 1972ccd979bdSMark Fasheh }; 1973ccd979bdSMark Fasheh 1974ccd979bdSMark Fasheh static int ocfs2_dlm_debug_release(struct inode *inode, struct file *file) 1975ccd979bdSMark Fasheh { 1976ccd979bdSMark Fasheh struct seq_file *seq = (struct seq_file *) file->private_data; 1977ccd979bdSMark Fasheh struct ocfs2_dlm_seq_priv *priv = seq->private; 1978ccd979bdSMark Fasheh struct ocfs2_lock_res *res = &priv->p_iter_res; 1979ccd979bdSMark Fasheh 1980ccd979bdSMark Fasheh ocfs2_remove_lockres_tracking(res); 1981ccd979bdSMark Fasheh ocfs2_put_dlm_debug(priv->p_dlm_debug); 1982ccd979bdSMark Fasheh return seq_release_private(inode, file); 1983ccd979bdSMark Fasheh } 1984ccd979bdSMark Fasheh 1985ccd979bdSMark Fasheh static int ocfs2_dlm_debug_open(struct inode *inode, struct file *file) 1986ccd979bdSMark Fasheh { 1987ccd979bdSMark Fasheh int ret; 1988ccd979bdSMark Fasheh struct ocfs2_dlm_seq_priv *priv; 1989ccd979bdSMark Fasheh struct seq_file *seq; 1990ccd979bdSMark Fasheh struct ocfs2_super *osb; 1991ccd979bdSMark Fasheh 1992ccd979bdSMark Fasheh priv = kzalloc(sizeof(struct ocfs2_dlm_seq_priv), GFP_KERNEL); 1993ccd979bdSMark Fasheh if (!priv) { 1994ccd979bdSMark Fasheh ret = -ENOMEM; 1995ccd979bdSMark Fasheh mlog_errno(ret); 1996ccd979bdSMark Fasheh goto out; 1997ccd979bdSMark Fasheh } 1998ccd979bdSMark Fasheh osb = (struct ocfs2_super *) inode->u.generic_ip; 1999ccd979bdSMark Fasheh ocfs2_get_dlm_debug(osb->osb_dlm_debug); 2000ccd979bdSMark Fasheh priv->p_dlm_debug = osb->osb_dlm_debug; 2001ccd979bdSMark Fasheh INIT_LIST_HEAD(&priv->p_iter_res.l_debug_list); 2002ccd979bdSMark Fasheh 2003ccd979bdSMark Fasheh ret = seq_open(file, &ocfs2_dlm_seq_ops); 2004ccd979bdSMark Fasheh if (ret) { 2005ccd979bdSMark Fasheh kfree(priv); 2006ccd979bdSMark Fasheh mlog_errno(ret); 2007ccd979bdSMark Fasheh goto out; 2008ccd979bdSMark Fasheh } 2009ccd979bdSMark Fasheh 2010ccd979bdSMark Fasheh seq = (struct seq_file *) file->private_data; 2011ccd979bdSMark Fasheh seq->private = priv; 2012ccd979bdSMark Fasheh 2013ccd979bdSMark Fasheh ocfs2_add_lockres_tracking(&priv->p_iter_res, 2014ccd979bdSMark Fasheh priv->p_dlm_debug); 2015ccd979bdSMark Fasheh 2016ccd979bdSMark Fasheh out: 2017ccd979bdSMark Fasheh return ret; 2018ccd979bdSMark Fasheh } 2019ccd979bdSMark Fasheh 2020ccd979bdSMark Fasheh static struct file_operations ocfs2_dlm_debug_fops = { 2021ccd979bdSMark Fasheh .open = ocfs2_dlm_debug_open, 2022ccd979bdSMark Fasheh .release = ocfs2_dlm_debug_release, 2023ccd979bdSMark Fasheh .read = seq_read, 2024ccd979bdSMark Fasheh .llseek = seq_lseek, 2025ccd979bdSMark Fasheh }; 2026ccd979bdSMark Fasheh 2027ccd979bdSMark Fasheh static int ocfs2_dlm_init_debug(struct ocfs2_super *osb) 2028ccd979bdSMark Fasheh { 2029ccd979bdSMark Fasheh int ret = 0; 2030ccd979bdSMark Fasheh struct ocfs2_dlm_debug *dlm_debug = osb->osb_dlm_debug; 2031ccd979bdSMark Fasheh 2032ccd979bdSMark Fasheh dlm_debug->d_locking_state = debugfs_create_file("locking_state", 2033ccd979bdSMark Fasheh S_IFREG|S_IRUSR, 2034ccd979bdSMark Fasheh osb->osb_debug_root, 2035ccd979bdSMark Fasheh osb, 2036ccd979bdSMark Fasheh &ocfs2_dlm_debug_fops); 2037ccd979bdSMark Fasheh if (!dlm_debug->d_locking_state) { 2038ccd979bdSMark Fasheh ret = -EINVAL; 2039ccd979bdSMark Fasheh mlog(ML_ERROR, 2040ccd979bdSMark Fasheh "Unable to create locking state debugfs file.\n"); 2041ccd979bdSMark Fasheh goto out; 2042ccd979bdSMark Fasheh } 2043ccd979bdSMark Fasheh 2044ccd979bdSMark Fasheh ocfs2_get_dlm_debug(dlm_debug); 2045ccd979bdSMark Fasheh out: 2046ccd979bdSMark Fasheh return ret; 2047ccd979bdSMark Fasheh } 2048ccd979bdSMark Fasheh 2049ccd979bdSMark Fasheh static void ocfs2_dlm_shutdown_debug(struct ocfs2_super *osb) 2050ccd979bdSMark Fasheh { 2051ccd979bdSMark Fasheh struct ocfs2_dlm_debug *dlm_debug = osb->osb_dlm_debug; 2052ccd979bdSMark Fasheh 2053ccd979bdSMark Fasheh if (dlm_debug) { 2054ccd979bdSMark Fasheh debugfs_remove(dlm_debug->d_locking_state); 2055ccd979bdSMark Fasheh ocfs2_put_dlm_debug(dlm_debug); 2056ccd979bdSMark Fasheh } 2057ccd979bdSMark Fasheh } 2058ccd979bdSMark Fasheh 2059ccd979bdSMark Fasheh int ocfs2_dlm_init(struct ocfs2_super *osb) 2060ccd979bdSMark Fasheh { 2061ccd979bdSMark Fasheh int status; 2062ccd979bdSMark Fasheh u32 dlm_key; 2063ccd979bdSMark Fasheh struct dlm_ctxt *dlm; 2064ccd979bdSMark Fasheh 2065ccd979bdSMark Fasheh mlog_entry_void(); 2066ccd979bdSMark Fasheh 2067ccd979bdSMark Fasheh status = ocfs2_dlm_init_debug(osb); 2068ccd979bdSMark Fasheh if (status < 0) { 2069ccd979bdSMark Fasheh mlog_errno(status); 2070ccd979bdSMark Fasheh goto bail; 2071ccd979bdSMark Fasheh } 2072ccd979bdSMark Fasheh 2073ccd979bdSMark Fasheh /* launch vote thread */ 2074ccd979bdSMark Fasheh osb->vote_task = kthread_run(ocfs2_vote_thread, osb, "ocfs2vote-%d", 2075ccd979bdSMark Fasheh osb->osb_id); 2076ccd979bdSMark Fasheh if (IS_ERR(osb->vote_task)) { 2077ccd979bdSMark Fasheh status = PTR_ERR(osb->vote_task); 2078ccd979bdSMark Fasheh osb->vote_task = NULL; 2079ccd979bdSMark Fasheh mlog_errno(status); 2080ccd979bdSMark Fasheh goto bail; 2081ccd979bdSMark Fasheh } 2082ccd979bdSMark Fasheh 2083ccd979bdSMark Fasheh /* used by the dlm code to make message headers unique, each 2084ccd979bdSMark Fasheh * node in this domain must agree on this. */ 2085ccd979bdSMark Fasheh dlm_key = crc32_le(0, osb->uuid_str, strlen(osb->uuid_str)); 2086ccd979bdSMark Fasheh 2087ccd979bdSMark Fasheh /* for now, uuid == domain */ 2088ccd979bdSMark Fasheh dlm = dlm_register_domain(osb->uuid_str, dlm_key); 2089ccd979bdSMark Fasheh if (IS_ERR(dlm)) { 2090ccd979bdSMark Fasheh status = PTR_ERR(dlm); 2091ccd979bdSMark Fasheh mlog_errno(status); 2092ccd979bdSMark Fasheh goto bail; 2093ccd979bdSMark Fasheh } 2094ccd979bdSMark Fasheh 2095ccd979bdSMark Fasheh ocfs2_super_lock_res_init(&osb->osb_super_lockres, osb); 2096ccd979bdSMark Fasheh ocfs2_rename_lock_res_init(&osb->osb_rename_lockres, osb); 2097ccd979bdSMark Fasheh 2098ccd979bdSMark Fasheh dlm_register_eviction_cb(dlm, &osb->osb_eviction_cb); 2099ccd979bdSMark Fasheh 2100ccd979bdSMark Fasheh osb->dlm = dlm; 2101ccd979bdSMark Fasheh 2102ccd979bdSMark Fasheh status = 0; 2103ccd979bdSMark Fasheh bail: 2104ccd979bdSMark Fasheh if (status < 0) { 2105ccd979bdSMark Fasheh ocfs2_dlm_shutdown_debug(osb); 2106ccd979bdSMark Fasheh if (osb->vote_task) 2107ccd979bdSMark Fasheh kthread_stop(osb->vote_task); 2108ccd979bdSMark Fasheh } 2109ccd979bdSMark Fasheh 2110ccd979bdSMark Fasheh mlog_exit(status); 2111ccd979bdSMark Fasheh return status; 2112ccd979bdSMark Fasheh } 2113ccd979bdSMark Fasheh 2114ccd979bdSMark Fasheh void ocfs2_dlm_shutdown(struct ocfs2_super *osb) 2115ccd979bdSMark Fasheh { 2116ccd979bdSMark Fasheh mlog_entry_void(); 2117ccd979bdSMark Fasheh 2118ccd979bdSMark Fasheh dlm_unregister_eviction_cb(&osb->osb_eviction_cb); 2119ccd979bdSMark Fasheh 2120ccd979bdSMark Fasheh ocfs2_drop_osb_locks(osb); 2121ccd979bdSMark Fasheh 2122ccd979bdSMark Fasheh if (osb->vote_task) { 2123ccd979bdSMark Fasheh kthread_stop(osb->vote_task); 2124ccd979bdSMark Fasheh osb->vote_task = NULL; 2125ccd979bdSMark Fasheh } 2126ccd979bdSMark Fasheh 2127ccd979bdSMark Fasheh ocfs2_lock_res_free(&osb->osb_super_lockres); 2128ccd979bdSMark Fasheh ocfs2_lock_res_free(&osb->osb_rename_lockres); 2129ccd979bdSMark Fasheh 2130ccd979bdSMark Fasheh dlm_unregister_domain(osb->dlm); 2131ccd979bdSMark Fasheh osb->dlm = NULL; 2132ccd979bdSMark Fasheh 2133ccd979bdSMark Fasheh ocfs2_dlm_shutdown_debug(osb); 2134ccd979bdSMark Fasheh 2135ccd979bdSMark Fasheh mlog_exit_void(); 2136ccd979bdSMark Fasheh } 2137ccd979bdSMark Fasheh 2138ccd979bdSMark Fasheh static void ocfs2_unlock_ast_func(void *opaque, enum dlm_status status) 2139ccd979bdSMark Fasheh { 2140ccd979bdSMark Fasheh struct ocfs2_lock_res *lockres = opaque; 2141ccd979bdSMark Fasheh unsigned long flags; 2142ccd979bdSMark Fasheh 2143ccd979bdSMark Fasheh mlog_entry_void(); 2144ccd979bdSMark Fasheh 2145ccd979bdSMark Fasheh mlog(0, "UNLOCK AST called on lock %s, action = %d\n", lockres->l_name, 2146ccd979bdSMark Fasheh lockres->l_unlock_action); 2147ccd979bdSMark Fasheh 2148ccd979bdSMark Fasheh spin_lock_irqsave(&lockres->l_lock, flags); 2149ccd979bdSMark Fasheh /* We tried to cancel a convert request, but it was already 2150ccd979bdSMark Fasheh * granted. All we want to do here is clear our unlock 2151ccd979bdSMark Fasheh * state. The wake_up call done at the bottom is redundant 2152ccd979bdSMark Fasheh * (ocfs2_prepare_cancel_convert doesn't sleep on this) but doesn't 2153ccd979bdSMark Fasheh * hurt anything anyway */ 2154ccd979bdSMark Fasheh if (status == DLM_CANCELGRANT && 2155ccd979bdSMark Fasheh lockres->l_unlock_action == OCFS2_UNLOCK_CANCEL_CONVERT) { 2156ccd979bdSMark Fasheh mlog(0, "Got cancelgrant for %s\n", lockres->l_name); 2157ccd979bdSMark Fasheh 2158ccd979bdSMark Fasheh /* We don't clear the busy flag in this case as it 2159ccd979bdSMark Fasheh * should have been cleared by the ast which the dlm 2160ccd979bdSMark Fasheh * has called. */ 2161ccd979bdSMark Fasheh goto complete_unlock; 2162ccd979bdSMark Fasheh } 2163ccd979bdSMark Fasheh 2164ccd979bdSMark Fasheh if (status != DLM_NORMAL) { 2165ccd979bdSMark Fasheh mlog(ML_ERROR, "Dlm passes status %d for lock %s, " 2166ccd979bdSMark Fasheh "unlock_action %d\n", status, lockres->l_name, 2167ccd979bdSMark Fasheh lockres->l_unlock_action); 2168ccd979bdSMark Fasheh spin_unlock_irqrestore(&lockres->l_lock, flags); 2169ccd979bdSMark Fasheh return; 2170ccd979bdSMark Fasheh } 2171ccd979bdSMark Fasheh 2172ccd979bdSMark Fasheh switch(lockres->l_unlock_action) { 2173ccd979bdSMark Fasheh case OCFS2_UNLOCK_CANCEL_CONVERT: 2174ccd979bdSMark Fasheh mlog(0, "Cancel convert success for %s\n", lockres->l_name); 2175ccd979bdSMark Fasheh lockres->l_action = OCFS2_AST_INVALID; 2176ccd979bdSMark Fasheh break; 2177ccd979bdSMark Fasheh case OCFS2_UNLOCK_DROP_LOCK: 2178ccd979bdSMark Fasheh lockres->l_level = LKM_IVMODE; 2179ccd979bdSMark Fasheh break; 2180ccd979bdSMark Fasheh default: 2181ccd979bdSMark Fasheh BUG(); 2182ccd979bdSMark Fasheh } 2183ccd979bdSMark Fasheh 2184ccd979bdSMark Fasheh lockres_clear_flags(lockres, OCFS2_LOCK_BUSY); 2185ccd979bdSMark Fasheh complete_unlock: 2186ccd979bdSMark Fasheh lockres->l_unlock_action = OCFS2_UNLOCK_INVALID; 2187ccd979bdSMark Fasheh spin_unlock_irqrestore(&lockres->l_lock, flags); 2188ccd979bdSMark Fasheh 2189ccd979bdSMark Fasheh wake_up(&lockres->l_event); 2190ccd979bdSMark Fasheh 2191ccd979bdSMark Fasheh mlog_exit_void(); 2192ccd979bdSMark Fasheh } 2193ccd979bdSMark Fasheh 2194ccd979bdSMark Fasheh typedef void (ocfs2_pre_drop_cb_t)(struct ocfs2_lock_res *, void *); 2195ccd979bdSMark Fasheh 2196ccd979bdSMark Fasheh struct drop_lock_cb { 2197ccd979bdSMark Fasheh ocfs2_pre_drop_cb_t *drop_func; 2198ccd979bdSMark Fasheh void *drop_data; 2199ccd979bdSMark Fasheh }; 2200ccd979bdSMark Fasheh 2201ccd979bdSMark Fasheh static int ocfs2_drop_lock(struct ocfs2_super *osb, 2202ccd979bdSMark Fasheh struct ocfs2_lock_res *lockres, 2203ccd979bdSMark Fasheh struct drop_lock_cb *dcb) 2204ccd979bdSMark Fasheh { 2205ccd979bdSMark Fasheh enum dlm_status status; 2206ccd979bdSMark Fasheh unsigned long flags; 2207ccd979bdSMark Fasheh 2208ccd979bdSMark Fasheh /* We didn't get anywhere near actually using this lockres. */ 2209ccd979bdSMark Fasheh if (!(lockres->l_flags & OCFS2_LOCK_INITIALIZED)) 2210ccd979bdSMark Fasheh goto out; 2211ccd979bdSMark Fasheh 2212ccd979bdSMark Fasheh spin_lock_irqsave(&lockres->l_lock, flags); 2213ccd979bdSMark Fasheh 2214ccd979bdSMark Fasheh mlog_bug_on_msg(!(lockres->l_flags & OCFS2_LOCK_FREEING), 2215ccd979bdSMark Fasheh "lockres %s, flags 0x%lx\n", 2216ccd979bdSMark Fasheh lockres->l_name, lockres->l_flags); 2217ccd979bdSMark Fasheh 2218ccd979bdSMark Fasheh while (lockres->l_flags & OCFS2_LOCK_BUSY) { 2219ccd979bdSMark Fasheh mlog(0, "waiting on busy lock \"%s\": flags = %lx, action = " 2220ccd979bdSMark Fasheh "%u, unlock_action = %u\n", 2221ccd979bdSMark Fasheh lockres->l_name, lockres->l_flags, lockres->l_action, 2222ccd979bdSMark Fasheh lockres->l_unlock_action); 2223ccd979bdSMark Fasheh 2224ccd979bdSMark Fasheh spin_unlock_irqrestore(&lockres->l_lock, flags); 2225ccd979bdSMark Fasheh 2226ccd979bdSMark Fasheh /* XXX: Today we just wait on any busy 2227ccd979bdSMark Fasheh * locks... Perhaps we need to cancel converts in the 2228ccd979bdSMark Fasheh * future? */ 2229ccd979bdSMark Fasheh ocfs2_wait_on_busy_lock(lockres); 2230ccd979bdSMark Fasheh 2231ccd979bdSMark Fasheh spin_lock_irqsave(&lockres->l_lock, flags); 2232ccd979bdSMark Fasheh } 2233ccd979bdSMark Fasheh 2234ccd979bdSMark Fasheh if (dcb) 2235ccd979bdSMark Fasheh dcb->drop_func(lockres, dcb->drop_data); 2236ccd979bdSMark Fasheh 2237ccd979bdSMark Fasheh if (lockres->l_flags & OCFS2_LOCK_BUSY) 2238ccd979bdSMark Fasheh mlog(ML_ERROR, "destroying busy lock: \"%s\"\n", 2239ccd979bdSMark Fasheh lockres->l_name); 2240ccd979bdSMark Fasheh if (lockres->l_flags & OCFS2_LOCK_BLOCKED) 2241ccd979bdSMark Fasheh mlog(0, "destroying blocked lock: \"%s\"\n", lockres->l_name); 2242ccd979bdSMark Fasheh 2243ccd979bdSMark Fasheh if (!(lockres->l_flags & OCFS2_LOCK_ATTACHED)) { 2244ccd979bdSMark Fasheh spin_unlock_irqrestore(&lockres->l_lock, flags); 2245ccd979bdSMark Fasheh goto out; 2246ccd979bdSMark Fasheh } 2247ccd979bdSMark Fasheh 2248ccd979bdSMark Fasheh lockres_clear_flags(lockres, OCFS2_LOCK_ATTACHED); 2249ccd979bdSMark Fasheh 2250ccd979bdSMark Fasheh /* make sure we never get here while waiting for an ast to 2251ccd979bdSMark Fasheh * fire. */ 2252ccd979bdSMark Fasheh BUG_ON(lockres->l_action != OCFS2_AST_INVALID); 2253ccd979bdSMark Fasheh 2254ccd979bdSMark Fasheh /* is this necessary? */ 2255ccd979bdSMark Fasheh lockres_or_flags(lockres, OCFS2_LOCK_BUSY); 2256ccd979bdSMark Fasheh lockres->l_unlock_action = OCFS2_UNLOCK_DROP_LOCK; 2257ccd979bdSMark Fasheh spin_unlock_irqrestore(&lockres->l_lock, flags); 2258ccd979bdSMark Fasheh 2259ccd979bdSMark Fasheh mlog(0, "lock %s\n", lockres->l_name); 2260ccd979bdSMark Fasheh 2261ccd979bdSMark Fasheh status = dlmunlock(osb->dlm, &lockres->l_lksb, LKM_VALBLK, 2262ccd979bdSMark Fasheh lockres->l_ops->unlock_ast, lockres); 2263ccd979bdSMark Fasheh if (status != DLM_NORMAL) { 2264ccd979bdSMark Fasheh ocfs2_log_dlm_error("dlmunlock", status, lockres); 2265ccd979bdSMark Fasheh mlog(ML_ERROR, "lockres flags: %lu\n", lockres->l_flags); 2266ccd979bdSMark Fasheh dlm_print_one_lock(lockres->l_lksb.lockid); 2267ccd979bdSMark Fasheh BUG(); 2268ccd979bdSMark Fasheh } 2269ccd979bdSMark Fasheh mlog(0, "lock %s, successfull return from dlmunlock\n", 2270ccd979bdSMark Fasheh lockres->l_name); 2271ccd979bdSMark Fasheh 2272ccd979bdSMark Fasheh ocfs2_wait_on_busy_lock(lockres); 2273ccd979bdSMark Fasheh out: 2274ccd979bdSMark Fasheh mlog_exit(0); 2275ccd979bdSMark Fasheh return 0; 2276ccd979bdSMark Fasheh } 2277ccd979bdSMark Fasheh 2278ccd979bdSMark Fasheh /* Mark the lockres as being dropped. It will no longer be 2279ccd979bdSMark Fasheh * queued if blocking, but we still may have to wait on it 2280ccd979bdSMark Fasheh * being dequeued from the vote thread before we can consider 2281ccd979bdSMark Fasheh * it safe to drop. 2282ccd979bdSMark Fasheh * 2283ccd979bdSMark Fasheh * You can *not* attempt to call cluster_lock on this lockres anymore. */ 2284ccd979bdSMark Fasheh void ocfs2_mark_lockres_freeing(struct ocfs2_lock_res *lockres) 2285ccd979bdSMark Fasheh { 2286ccd979bdSMark Fasheh int status; 2287ccd979bdSMark Fasheh struct ocfs2_mask_waiter mw; 2288ccd979bdSMark Fasheh unsigned long flags; 2289ccd979bdSMark Fasheh 2290ccd979bdSMark Fasheh ocfs2_init_mask_waiter(&mw); 2291ccd979bdSMark Fasheh 2292ccd979bdSMark Fasheh spin_lock_irqsave(&lockres->l_lock, flags); 2293ccd979bdSMark Fasheh lockres->l_flags |= OCFS2_LOCK_FREEING; 2294ccd979bdSMark Fasheh while (lockres->l_flags & OCFS2_LOCK_QUEUED) { 2295ccd979bdSMark Fasheh lockres_add_mask_waiter(lockres, &mw, OCFS2_LOCK_QUEUED, 0); 2296ccd979bdSMark Fasheh spin_unlock_irqrestore(&lockres->l_lock, flags); 2297ccd979bdSMark Fasheh 2298ccd979bdSMark Fasheh mlog(0, "Waiting on lockres %s\n", lockres->l_name); 2299ccd979bdSMark Fasheh 2300ccd979bdSMark Fasheh status = ocfs2_wait_for_mask(&mw); 2301ccd979bdSMark Fasheh if (status) 2302ccd979bdSMark Fasheh mlog_errno(status); 2303ccd979bdSMark Fasheh 2304ccd979bdSMark Fasheh spin_lock_irqsave(&lockres->l_lock, flags); 2305ccd979bdSMark Fasheh } 2306ccd979bdSMark Fasheh spin_unlock_irqrestore(&lockres->l_lock, flags); 2307ccd979bdSMark Fasheh } 2308ccd979bdSMark Fasheh 2309ccd979bdSMark Fasheh static void ocfs2_drop_osb_locks(struct ocfs2_super *osb) 2310ccd979bdSMark Fasheh { 2311ccd979bdSMark Fasheh int status; 2312ccd979bdSMark Fasheh 2313ccd979bdSMark Fasheh mlog_entry_void(); 2314ccd979bdSMark Fasheh 2315ccd979bdSMark Fasheh ocfs2_mark_lockres_freeing(&osb->osb_super_lockres); 2316ccd979bdSMark Fasheh 2317ccd979bdSMark Fasheh status = ocfs2_drop_lock(osb, &osb->osb_super_lockres, NULL); 2318ccd979bdSMark Fasheh if (status < 0) 2319ccd979bdSMark Fasheh mlog_errno(status); 2320ccd979bdSMark Fasheh 2321ccd979bdSMark Fasheh ocfs2_mark_lockres_freeing(&osb->osb_rename_lockres); 2322ccd979bdSMark Fasheh 2323ccd979bdSMark Fasheh status = ocfs2_drop_lock(osb, &osb->osb_rename_lockres, NULL); 2324ccd979bdSMark Fasheh if (status < 0) 2325ccd979bdSMark Fasheh mlog_errno(status); 2326ccd979bdSMark Fasheh 2327ccd979bdSMark Fasheh mlog_exit(status); 2328ccd979bdSMark Fasheh } 2329ccd979bdSMark Fasheh 2330ccd979bdSMark Fasheh static void ocfs2_meta_pre_drop(struct ocfs2_lock_res *lockres, void *data) 2331ccd979bdSMark Fasheh { 2332ccd979bdSMark Fasheh struct inode *inode = data; 2333ccd979bdSMark Fasheh 2334ccd979bdSMark Fasheh /* the metadata lock requires a bit more work as we have an 2335ccd979bdSMark Fasheh * LVB to worry about. */ 2336ccd979bdSMark Fasheh if (lockres->l_flags & OCFS2_LOCK_ATTACHED && 2337ccd979bdSMark Fasheh lockres->l_level == LKM_EXMODE && 2338ccd979bdSMark Fasheh !(lockres->l_flags & OCFS2_LOCK_NEEDS_REFRESH)) 2339ccd979bdSMark Fasheh __ocfs2_stuff_meta_lvb(inode); 2340ccd979bdSMark Fasheh } 2341ccd979bdSMark Fasheh 2342ccd979bdSMark Fasheh int ocfs2_drop_inode_locks(struct inode *inode) 2343ccd979bdSMark Fasheh { 2344ccd979bdSMark Fasheh int status, err; 2345ccd979bdSMark Fasheh struct drop_lock_cb meta_dcb = { ocfs2_meta_pre_drop, inode, }; 2346ccd979bdSMark Fasheh 2347ccd979bdSMark Fasheh mlog_entry_void(); 2348ccd979bdSMark Fasheh 2349ccd979bdSMark Fasheh /* No need to call ocfs2_mark_lockres_freeing here - 2350ccd979bdSMark Fasheh * ocfs2_clear_inode has done it for us. */ 2351ccd979bdSMark Fasheh 2352ccd979bdSMark Fasheh err = ocfs2_drop_lock(OCFS2_SB(inode->i_sb), 2353ccd979bdSMark Fasheh &OCFS2_I(inode)->ip_data_lockres, 2354ccd979bdSMark Fasheh NULL); 2355ccd979bdSMark Fasheh if (err < 0) 2356ccd979bdSMark Fasheh mlog_errno(err); 2357ccd979bdSMark Fasheh 2358ccd979bdSMark Fasheh status = err; 2359ccd979bdSMark Fasheh 2360ccd979bdSMark Fasheh err = ocfs2_drop_lock(OCFS2_SB(inode->i_sb), 2361ccd979bdSMark Fasheh &OCFS2_I(inode)->ip_meta_lockres, 2362ccd979bdSMark Fasheh &meta_dcb); 2363ccd979bdSMark Fasheh if (err < 0) 2364ccd979bdSMark Fasheh mlog_errno(err); 2365ccd979bdSMark Fasheh if (err < 0 && !status) 2366ccd979bdSMark Fasheh status = err; 2367ccd979bdSMark Fasheh 2368ccd979bdSMark Fasheh err = ocfs2_drop_lock(OCFS2_SB(inode->i_sb), 2369ccd979bdSMark Fasheh &OCFS2_I(inode)->ip_rw_lockres, 2370ccd979bdSMark Fasheh NULL); 2371ccd979bdSMark Fasheh if (err < 0) 2372ccd979bdSMark Fasheh mlog_errno(err); 2373ccd979bdSMark Fasheh if (err < 0 && !status) 2374ccd979bdSMark Fasheh status = err; 2375ccd979bdSMark Fasheh 2376ccd979bdSMark Fasheh mlog_exit(status); 2377ccd979bdSMark Fasheh return status; 2378ccd979bdSMark Fasheh } 2379ccd979bdSMark Fasheh 2380ccd979bdSMark Fasheh static void ocfs2_prepare_downconvert(struct ocfs2_lock_res *lockres, 2381ccd979bdSMark Fasheh int new_level) 2382ccd979bdSMark Fasheh { 2383ccd979bdSMark Fasheh assert_spin_locked(&lockres->l_lock); 2384ccd979bdSMark Fasheh 2385ccd979bdSMark Fasheh BUG_ON(lockres->l_blocking <= LKM_NLMODE); 2386ccd979bdSMark Fasheh 2387ccd979bdSMark Fasheh if (lockres->l_level <= new_level) { 2388ccd979bdSMark Fasheh mlog(ML_ERROR, "lockres->l_level (%u) <= new_level (%u)\n", 2389ccd979bdSMark Fasheh lockres->l_level, new_level); 2390ccd979bdSMark Fasheh BUG(); 2391ccd979bdSMark Fasheh } 2392ccd979bdSMark Fasheh 2393ccd979bdSMark Fasheh mlog(0, "lock %s, new_level = %d, l_blocking = %d\n", 2394ccd979bdSMark Fasheh lockres->l_name, new_level, lockres->l_blocking); 2395ccd979bdSMark Fasheh 2396ccd979bdSMark Fasheh lockres->l_action = OCFS2_AST_DOWNCONVERT; 2397ccd979bdSMark Fasheh lockres->l_requested = new_level; 2398ccd979bdSMark Fasheh lockres_or_flags(lockres, OCFS2_LOCK_BUSY); 2399ccd979bdSMark Fasheh } 2400ccd979bdSMark Fasheh 2401ccd979bdSMark Fasheh static int ocfs2_downconvert_lock(struct ocfs2_super *osb, 2402ccd979bdSMark Fasheh struct ocfs2_lock_res *lockres, 2403ccd979bdSMark Fasheh int new_level, 2404ccd979bdSMark Fasheh int lvb) 2405ccd979bdSMark Fasheh { 2406ccd979bdSMark Fasheh int ret, dlm_flags = LKM_CONVERT; 2407ccd979bdSMark Fasheh enum dlm_status status; 2408ccd979bdSMark Fasheh 2409ccd979bdSMark Fasheh mlog_entry_void(); 2410ccd979bdSMark Fasheh 2411ccd979bdSMark Fasheh if (lvb) 2412ccd979bdSMark Fasheh dlm_flags |= LKM_VALBLK; 2413ccd979bdSMark Fasheh 2414ccd979bdSMark Fasheh status = dlmlock(osb->dlm, 2415ccd979bdSMark Fasheh new_level, 2416ccd979bdSMark Fasheh &lockres->l_lksb, 2417ccd979bdSMark Fasheh dlm_flags, 2418ccd979bdSMark Fasheh lockres->l_name, 2419ccd979bdSMark Fasheh lockres->l_ops->ast, 2420ccd979bdSMark Fasheh lockres, 2421ccd979bdSMark Fasheh lockres->l_ops->bast); 2422ccd979bdSMark Fasheh if (status != DLM_NORMAL) { 2423ccd979bdSMark Fasheh ocfs2_log_dlm_error("dlmlock", status, lockres); 2424ccd979bdSMark Fasheh ret = -EINVAL; 2425ccd979bdSMark Fasheh ocfs2_recover_from_dlm_error(lockres, 1); 2426ccd979bdSMark Fasheh goto bail; 2427ccd979bdSMark Fasheh } 2428ccd979bdSMark Fasheh 2429ccd979bdSMark Fasheh ret = 0; 2430ccd979bdSMark Fasheh bail: 2431ccd979bdSMark Fasheh mlog_exit(ret); 2432ccd979bdSMark Fasheh return ret; 2433ccd979bdSMark Fasheh } 2434ccd979bdSMark Fasheh 2435ccd979bdSMark Fasheh /* returns 1 when the caller should unlock and call dlmunlock */ 2436ccd979bdSMark Fasheh static int ocfs2_prepare_cancel_convert(struct ocfs2_super *osb, 2437ccd979bdSMark Fasheh struct ocfs2_lock_res *lockres) 2438ccd979bdSMark Fasheh { 2439ccd979bdSMark Fasheh assert_spin_locked(&lockres->l_lock); 2440ccd979bdSMark Fasheh 2441ccd979bdSMark Fasheh mlog_entry_void(); 2442ccd979bdSMark Fasheh mlog(0, "lock %s\n", lockres->l_name); 2443ccd979bdSMark Fasheh 2444ccd979bdSMark Fasheh if (lockres->l_unlock_action == OCFS2_UNLOCK_CANCEL_CONVERT) { 2445ccd979bdSMark Fasheh /* If we're already trying to cancel a lock conversion 2446ccd979bdSMark Fasheh * then just drop the spinlock and allow the caller to 2447ccd979bdSMark Fasheh * requeue this lock. */ 2448ccd979bdSMark Fasheh 2449ccd979bdSMark Fasheh mlog(0, "Lockres %s, skip convert\n", lockres->l_name); 2450ccd979bdSMark Fasheh return 0; 2451ccd979bdSMark Fasheh } 2452ccd979bdSMark Fasheh 2453ccd979bdSMark Fasheh /* were we in a convert when we got the bast fire? */ 2454ccd979bdSMark Fasheh BUG_ON(lockres->l_action != OCFS2_AST_CONVERT && 2455ccd979bdSMark Fasheh lockres->l_action != OCFS2_AST_DOWNCONVERT); 2456ccd979bdSMark Fasheh /* set things up for the unlockast to know to just 2457ccd979bdSMark Fasheh * clear out the ast_action and unset busy, etc. */ 2458ccd979bdSMark Fasheh lockres->l_unlock_action = OCFS2_UNLOCK_CANCEL_CONVERT; 2459ccd979bdSMark Fasheh 2460ccd979bdSMark Fasheh mlog_bug_on_msg(!(lockres->l_flags & OCFS2_LOCK_BUSY), 2461ccd979bdSMark Fasheh "lock %s, invalid flags: 0x%lx\n", 2462ccd979bdSMark Fasheh lockres->l_name, lockres->l_flags); 2463ccd979bdSMark Fasheh 2464ccd979bdSMark Fasheh return 1; 2465ccd979bdSMark Fasheh } 2466ccd979bdSMark Fasheh 2467ccd979bdSMark Fasheh static int ocfs2_cancel_convert(struct ocfs2_super *osb, 2468ccd979bdSMark Fasheh struct ocfs2_lock_res *lockres) 2469ccd979bdSMark Fasheh { 2470ccd979bdSMark Fasheh int ret; 2471ccd979bdSMark Fasheh enum dlm_status status; 2472ccd979bdSMark Fasheh 2473ccd979bdSMark Fasheh mlog_entry_void(); 2474ccd979bdSMark Fasheh mlog(0, "lock %s\n", lockres->l_name); 2475ccd979bdSMark Fasheh 2476ccd979bdSMark Fasheh ret = 0; 2477ccd979bdSMark Fasheh status = dlmunlock(osb->dlm, 2478ccd979bdSMark Fasheh &lockres->l_lksb, 2479ccd979bdSMark Fasheh LKM_CANCEL, 2480ccd979bdSMark Fasheh lockres->l_ops->unlock_ast, 2481ccd979bdSMark Fasheh lockres); 2482ccd979bdSMark Fasheh if (status != DLM_NORMAL) { 2483ccd979bdSMark Fasheh ocfs2_log_dlm_error("dlmunlock", status, lockres); 2484ccd979bdSMark Fasheh ret = -EINVAL; 2485ccd979bdSMark Fasheh ocfs2_recover_from_dlm_error(lockres, 0); 2486ccd979bdSMark Fasheh } 2487ccd979bdSMark Fasheh 2488ccd979bdSMark Fasheh mlog(0, "lock %s return from dlmunlock\n", lockres->l_name); 2489ccd979bdSMark Fasheh 2490ccd979bdSMark Fasheh mlog_exit(ret); 2491ccd979bdSMark Fasheh return ret; 2492ccd979bdSMark Fasheh } 2493ccd979bdSMark Fasheh 2494ccd979bdSMark Fasheh static inline int ocfs2_can_downconvert_meta_lock(struct inode *inode, 2495ccd979bdSMark Fasheh struct ocfs2_lock_res *lockres, 2496ccd979bdSMark Fasheh int new_level) 2497ccd979bdSMark Fasheh { 2498ccd979bdSMark Fasheh int ret; 2499ccd979bdSMark Fasheh 2500ccd979bdSMark Fasheh mlog_entry_void(); 2501ccd979bdSMark Fasheh 2502ccd979bdSMark Fasheh BUG_ON(new_level != LKM_NLMODE && new_level != LKM_PRMODE); 2503ccd979bdSMark Fasheh 2504ccd979bdSMark Fasheh if (lockres->l_flags & OCFS2_LOCK_REFRESHING) { 2505ccd979bdSMark Fasheh ret = 0; 2506ccd979bdSMark Fasheh mlog(0, "lockres %s currently being refreshed -- backing " 2507ccd979bdSMark Fasheh "off!\n", lockres->l_name); 2508ccd979bdSMark Fasheh } else if (new_level == LKM_PRMODE) 2509ccd979bdSMark Fasheh ret = !lockres->l_ex_holders && 2510ccd979bdSMark Fasheh ocfs2_inode_fully_checkpointed(inode); 2511ccd979bdSMark Fasheh else /* Must be NLMODE we're converting to. */ 2512ccd979bdSMark Fasheh ret = !lockres->l_ro_holders && !lockres->l_ex_holders && 2513ccd979bdSMark Fasheh ocfs2_inode_fully_checkpointed(inode); 2514ccd979bdSMark Fasheh 2515ccd979bdSMark Fasheh mlog_exit(ret); 2516ccd979bdSMark Fasheh return ret; 2517ccd979bdSMark Fasheh } 2518ccd979bdSMark Fasheh 2519ccd979bdSMark Fasheh static int ocfs2_do_unblock_meta(struct inode *inode, 2520ccd979bdSMark Fasheh int *requeue) 2521ccd979bdSMark Fasheh { 2522ccd979bdSMark Fasheh int new_level; 2523ccd979bdSMark Fasheh int set_lvb = 0; 2524ccd979bdSMark Fasheh int ret = 0; 2525ccd979bdSMark Fasheh struct ocfs2_lock_res *lockres = &OCFS2_I(inode)->ip_meta_lockres; 2526ccd979bdSMark Fasheh unsigned long flags; 2527ccd979bdSMark Fasheh 2528ccd979bdSMark Fasheh struct ocfs2_super *osb = OCFS2_SB(inode->i_sb); 2529ccd979bdSMark Fasheh 2530ccd979bdSMark Fasheh mlog_entry_void(); 2531ccd979bdSMark Fasheh 2532ccd979bdSMark Fasheh spin_lock_irqsave(&lockres->l_lock, flags); 2533ccd979bdSMark Fasheh 2534ccd979bdSMark Fasheh BUG_ON(!(lockres->l_flags & OCFS2_LOCK_BLOCKED)); 2535ccd979bdSMark Fasheh 2536ccd979bdSMark Fasheh mlog(0, "l_level=%d, l_blocking=%d\n", lockres->l_level, 2537ccd979bdSMark Fasheh lockres->l_blocking); 2538ccd979bdSMark Fasheh 2539ccd979bdSMark Fasheh BUG_ON(lockres->l_level != LKM_EXMODE && 2540ccd979bdSMark Fasheh lockres->l_level != LKM_PRMODE); 2541ccd979bdSMark Fasheh 2542ccd979bdSMark Fasheh if (lockres->l_flags & OCFS2_LOCK_BUSY) { 2543ccd979bdSMark Fasheh *requeue = 1; 2544ccd979bdSMark Fasheh ret = ocfs2_prepare_cancel_convert(osb, lockres); 2545ccd979bdSMark Fasheh spin_unlock_irqrestore(&lockres->l_lock, flags); 2546ccd979bdSMark Fasheh if (ret) { 2547ccd979bdSMark Fasheh ret = ocfs2_cancel_convert(osb, lockres); 2548ccd979bdSMark Fasheh if (ret < 0) 2549ccd979bdSMark Fasheh mlog_errno(ret); 2550ccd979bdSMark Fasheh } 2551ccd979bdSMark Fasheh goto leave; 2552ccd979bdSMark Fasheh } 2553ccd979bdSMark Fasheh 2554ccd979bdSMark Fasheh new_level = ocfs2_highest_compat_lock_level(lockres->l_blocking); 2555ccd979bdSMark Fasheh 2556ccd979bdSMark Fasheh mlog(0, "l_level=%d, l_blocking=%d, new_level=%d\n", 2557ccd979bdSMark Fasheh lockres->l_level, lockres->l_blocking, new_level); 2558ccd979bdSMark Fasheh 2559ccd979bdSMark Fasheh if (ocfs2_can_downconvert_meta_lock(inode, lockres, new_level)) { 2560ccd979bdSMark Fasheh if (lockres->l_level == LKM_EXMODE) 2561ccd979bdSMark Fasheh set_lvb = 1; 2562ccd979bdSMark Fasheh 2563ccd979bdSMark Fasheh /* If the lock hasn't been refreshed yet (rare), then 2564ccd979bdSMark Fasheh * our memory inode values are old and we skip 2565ccd979bdSMark Fasheh * stuffing the lvb. There's no need to actually clear 2566ccd979bdSMark Fasheh * out the lvb here as it's value is still valid. */ 2567ccd979bdSMark Fasheh if (!(lockres->l_flags & OCFS2_LOCK_NEEDS_REFRESH)) { 2568ccd979bdSMark Fasheh if (set_lvb) 2569ccd979bdSMark Fasheh __ocfs2_stuff_meta_lvb(inode); 2570ccd979bdSMark Fasheh } else 2571ccd979bdSMark Fasheh mlog(0, "lockres %s: downconverting stale lock!\n", 2572ccd979bdSMark Fasheh lockres->l_name); 2573ccd979bdSMark Fasheh 2574ccd979bdSMark Fasheh mlog(0, "calling ocfs2_downconvert_lock with l_level=%d, " 2575ccd979bdSMark Fasheh "l_blocking=%d, new_level=%d\n", 2576ccd979bdSMark Fasheh lockres->l_level, lockres->l_blocking, new_level); 2577ccd979bdSMark Fasheh 2578ccd979bdSMark Fasheh ocfs2_prepare_downconvert(lockres, new_level); 2579ccd979bdSMark Fasheh spin_unlock_irqrestore(&lockres->l_lock, flags); 2580ccd979bdSMark Fasheh ret = ocfs2_downconvert_lock(osb, lockres, new_level, set_lvb); 2581ccd979bdSMark Fasheh goto leave; 2582ccd979bdSMark Fasheh } 2583ccd979bdSMark Fasheh if (!ocfs2_inode_fully_checkpointed(inode)) 2584ccd979bdSMark Fasheh ocfs2_start_checkpoint(osb); 2585ccd979bdSMark Fasheh 2586ccd979bdSMark Fasheh *requeue = 1; 2587ccd979bdSMark Fasheh spin_unlock_irqrestore(&lockres->l_lock, flags); 2588ccd979bdSMark Fasheh ret = 0; 2589ccd979bdSMark Fasheh leave: 2590ccd979bdSMark Fasheh mlog_exit(ret); 2591ccd979bdSMark Fasheh return ret; 2592ccd979bdSMark Fasheh } 2593ccd979bdSMark Fasheh 2594ccd979bdSMark Fasheh static int ocfs2_generic_unblock_lock(struct ocfs2_super *osb, 2595ccd979bdSMark Fasheh struct ocfs2_lock_res *lockres, 2596ccd979bdSMark Fasheh int *requeue, 2597ccd979bdSMark Fasheh ocfs2_convert_worker_t *worker) 2598ccd979bdSMark Fasheh { 2599ccd979bdSMark Fasheh unsigned long flags; 2600ccd979bdSMark Fasheh int blocking; 2601ccd979bdSMark Fasheh int new_level; 2602ccd979bdSMark Fasheh int ret = 0; 2603ccd979bdSMark Fasheh 2604ccd979bdSMark Fasheh mlog_entry_void(); 2605ccd979bdSMark Fasheh 2606ccd979bdSMark Fasheh spin_lock_irqsave(&lockres->l_lock, flags); 2607ccd979bdSMark Fasheh 2608ccd979bdSMark Fasheh BUG_ON(!(lockres->l_flags & OCFS2_LOCK_BLOCKED)); 2609ccd979bdSMark Fasheh 2610ccd979bdSMark Fasheh recheck: 2611ccd979bdSMark Fasheh if (lockres->l_flags & OCFS2_LOCK_BUSY) { 2612ccd979bdSMark Fasheh *requeue = 1; 2613ccd979bdSMark Fasheh ret = ocfs2_prepare_cancel_convert(osb, lockres); 2614ccd979bdSMark Fasheh spin_unlock_irqrestore(&lockres->l_lock, flags); 2615ccd979bdSMark Fasheh if (ret) { 2616ccd979bdSMark Fasheh ret = ocfs2_cancel_convert(osb, lockres); 2617ccd979bdSMark Fasheh if (ret < 0) 2618ccd979bdSMark Fasheh mlog_errno(ret); 2619ccd979bdSMark Fasheh } 2620ccd979bdSMark Fasheh goto leave; 2621ccd979bdSMark Fasheh } 2622ccd979bdSMark Fasheh 2623ccd979bdSMark Fasheh /* if we're blocking an exclusive and we have *any* holders, 2624ccd979bdSMark Fasheh * then requeue. */ 2625ccd979bdSMark Fasheh if ((lockres->l_blocking == LKM_EXMODE) 2626ccd979bdSMark Fasheh && (lockres->l_ex_holders || lockres->l_ro_holders)) { 2627ccd979bdSMark Fasheh spin_unlock_irqrestore(&lockres->l_lock, flags); 2628ccd979bdSMark Fasheh *requeue = 1; 2629ccd979bdSMark Fasheh ret = 0; 2630ccd979bdSMark Fasheh goto leave; 2631ccd979bdSMark Fasheh } 2632ccd979bdSMark Fasheh 2633ccd979bdSMark Fasheh /* If it's a PR we're blocking, then only 2634ccd979bdSMark Fasheh * requeue if we've got any EX holders */ 2635ccd979bdSMark Fasheh if (lockres->l_blocking == LKM_PRMODE && 2636ccd979bdSMark Fasheh lockres->l_ex_holders) { 2637ccd979bdSMark Fasheh spin_unlock_irqrestore(&lockres->l_lock, flags); 2638ccd979bdSMark Fasheh *requeue = 1; 2639ccd979bdSMark Fasheh ret = 0; 2640ccd979bdSMark Fasheh goto leave; 2641ccd979bdSMark Fasheh } 2642ccd979bdSMark Fasheh 2643ccd979bdSMark Fasheh /* If we get here, then we know that there are no more 2644ccd979bdSMark Fasheh * incompatible holders (and anyone asking for an incompatible 2645ccd979bdSMark Fasheh * lock is blocked). We can now downconvert the lock */ 2646ccd979bdSMark Fasheh if (!worker) 2647ccd979bdSMark Fasheh goto downconvert; 2648ccd979bdSMark Fasheh 2649ccd979bdSMark Fasheh /* Some lockres types want to do a bit of work before 2650ccd979bdSMark Fasheh * downconverting a lock. Allow that here. The worker function 2651ccd979bdSMark Fasheh * may sleep, so we save off a copy of what we're blocking as 2652ccd979bdSMark Fasheh * it may change while we're not holding the spin lock. */ 2653ccd979bdSMark Fasheh blocking = lockres->l_blocking; 2654ccd979bdSMark Fasheh spin_unlock_irqrestore(&lockres->l_lock, flags); 2655ccd979bdSMark Fasheh 2656ccd979bdSMark Fasheh worker(lockres, blocking); 2657ccd979bdSMark Fasheh 2658ccd979bdSMark Fasheh spin_lock_irqsave(&lockres->l_lock, flags); 2659ccd979bdSMark Fasheh if (blocking != lockres->l_blocking) { 2660ccd979bdSMark Fasheh /* If this changed underneath us, then we can't drop 2661ccd979bdSMark Fasheh * it just yet. */ 2662ccd979bdSMark Fasheh goto recheck; 2663ccd979bdSMark Fasheh } 2664ccd979bdSMark Fasheh 2665ccd979bdSMark Fasheh downconvert: 2666ccd979bdSMark Fasheh *requeue = 0; 2667ccd979bdSMark Fasheh new_level = ocfs2_highest_compat_lock_level(lockres->l_blocking); 2668ccd979bdSMark Fasheh 2669ccd979bdSMark Fasheh ocfs2_prepare_downconvert(lockres, new_level); 2670ccd979bdSMark Fasheh spin_unlock_irqrestore(&lockres->l_lock, flags); 2671ccd979bdSMark Fasheh ret = ocfs2_downconvert_lock(osb, lockres, new_level, 0); 2672ccd979bdSMark Fasheh leave: 2673ccd979bdSMark Fasheh mlog_exit(ret); 2674ccd979bdSMark Fasheh return ret; 2675ccd979bdSMark Fasheh } 2676ccd979bdSMark Fasheh 2677ccd979bdSMark Fasheh static void ocfs2_data_convert_worker(struct ocfs2_lock_res *lockres, 2678ccd979bdSMark Fasheh int blocking) 2679ccd979bdSMark Fasheh { 2680ccd979bdSMark Fasheh struct inode *inode; 2681ccd979bdSMark Fasheh struct address_space *mapping; 2682ccd979bdSMark Fasheh 2683ccd979bdSMark Fasheh mlog_entry_void(); 2684ccd979bdSMark Fasheh 2685ccd979bdSMark Fasheh inode = ocfs2_lock_res_inode(lockres); 2686ccd979bdSMark Fasheh mapping = inode->i_mapping; 2687ccd979bdSMark Fasheh 2688ccd979bdSMark Fasheh if (filemap_fdatawrite(mapping)) { 2689b0697053SMark Fasheh mlog(ML_ERROR, "Could not sync inode %llu for downconvert!", 2690b0697053SMark Fasheh (unsigned long long)OCFS2_I(inode)->ip_blkno); 2691ccd979bdSMark Fasheh } 2692ccd979bdSMark Fasheh sync_mapping_buffers(mapping); 2693ccd979bdSMark Fasheh if (blocking == LKM_EXMODE) { 2694ccd979bdSMark Fasheh truncate_inode_pages(mapping, 0); 2695ccd979bdSMark Fasheh unmap_mapping_range(mapping, 0, 0, 0); 2696ccd979bdSMark Fasheh } else { 2697ccd979bdSMark Fasheh /* We only need to wait on the I/O if we're not also 2698ccd979bdSMark Fasheh * truncating pages because truncate_inode_pages waits 2699ccd979bdSMark Fasheh * for us above. We don't truncate pages if we're 2700ccd979bdSMark Fasheh * blocking anything < EXMODE because we want to keep 2701ccd979bdSMark Fasheh * them around in that case. */ 2702ccd979bdSMark Fasheh filemap_fdatawait(mapping); 2703ccd979bdSMark Fasheh } 2704ccd979bdSMark Fasheh 2705ccd979bdSMark Fasheh mlog_exit_void(); 2706ccd979bdSMark Fasheh } 2707ccd979bdSMark Fasheh 2708ccd979bdSMark Fasheh int ocfs2_unblock_data(struct ocfs2_lock_res *lockres, 2709ccd979bdSMark Fasheh int *requeue) 2710ccd979bdSMark Fasheh { 2711ccd979bdSMark Fasheh int status; 2712ccd979bdSMark Fasheh struct inode *inode; 2713ccd979bdSMark Fasheh struct ocfs2_super *osb; 2714ccd979bdSMark Fasheh 2715ccd979bdSMark Fasheh mlog_entry_void(); 2716ccd979bdSMark Fasheh 2717ccd979bdSMark Fasheh inode = ocfs2_lock_res_inode(lockres); 2718ccd979bdSMark Fasheh osb = OCFS2_SB(inode->i_sb); 2719ccd979bdSMark Fasheh 2720b0697053SMark Fasheh mlog(0, "unblock inode %llu\n", 2721b0697053SMark Fasheh (unsigned long long)OCFS2_I(inode)->ip_blkno); 2722ccd979bdSMark Fasheh 2723ccd979bdSMark Fasheh status = ocfs2_generic_unblock_lock(osb, 2724ccd979bdSMark Fasheh lockres, 2725ccd979bdSMark Fasheh requeue, 2726ccd979bdSMark Fasheh ocfs2_data_convert_worker); 2727ccd979bdSMark Fasheh if (status < 0) 2728ccd979bdSMark Fasheh mlog_errno(status); 2729ccd979bdSMark Fasheh 2730b0697053SMark Fasheh mlog(0, "inode %llu, requeue = %d\n", 2731b0697053SMark Fasheh (unsigned long long)OCFS2_I(inode)->ip_blkno, *requeue); 2732ccd979bdSMark Fasheh 2733ccd979bdSMark Fasheh mlog_exit(status); 2734ccd979bdSMark Fasheh return status; 2735ccd979bdSMark Fasheh } 2736ccd979bdSMark Fasheh 2737ccd979bdSMark Fasheh static int ocfs2_unblock_inode_lock(struct ocfs2_lock_res *lockres, 2738ccd979bdSMark Fasheh int *requeue) 2739ccd979bdSMark Fasheh { 2740ccd979bdSMark Fasheh int status; 2741ccd979bdSMark Fasheh struct inode *inode; 2742ccd979bdSMark Fasheh 2743ccd979bdSMark Fasheh mlog_entry_void(); 2744ccd979bdSMark Fasheh 2745ccd979bdSMark Fasheh mlog(0, "Unblock lockres %s\n", lockres->l_name); 2746ccd979bdSMark Fasheh 2747ccd979bdSMark Fasheh inode = ocfs2_lock_res_inode(lockres); 2748ccd979bdSMark Fasheh 2749ccd979bdSMark Fasheh status = ocfs2_generic_unblock_lock(OCFS2_SB(inode->i_sb), 2750ccd979bdSMark Fasheh lockres, 2751ccd979bdSMark Fasheh requeue, 2752ccd979bdSMark Fasheh NULL); 2753ccd979bdSMark Fasheh if (status < 0) 2754ccd979bdSMark Fasheh mlog_errno(status); 2755ccd979bdSMark Fasheh 2756ccd979bdSMark Fasheh mlog_exit(status); 2757ccd979bdSMark Fasheh return status; 2758ccd979bdSMark Fasheh } 2759ccd979bdSMark Fasheh 2760ccd979bdSMark Fasheh 2761ccd979bdSMark Fasheh int ocfs2_unblock_meta(struct ocfs2_lock_res *lockres, 2762ccd979bdSMark Fasheh int *requeue) 2763ccd979bdSMark Fasheh { 2764ccd979bdSMark Fasheh int status; 2765ccd979bdSMark Fasheh struct inode *inode; 2766ccd979bdSMark Fasheh 2767ccd979bdSMark Fasheh mlog_entry_void(); 2768ccd979bdSMark Fasheh 2769ccd979bdSMark Fasheh inode = ocfs2_lock_res_inode(lockres); 2770ccd979bdSMark Fasheh 2771b0697053SMark Fasheh mlog(0, "unblock inode %llu\n", 2772b0697053SMark Fasheh (unsigned long long)OCFS2_I(inode)->ip_blkno); 2773ccd979bdSMark Fasheh 2774ccd979bdSMark Fasheh status = ocfs2_do_unblock_meta(inode, requeue); 2775ccd979bdSMark Fasheh if (status < 0) 2776ccd979bdSMark Fasheh mlog_errno(status); 2777ccd979bdSMark Fasheh 2778b0697053SMark Fasheh mlog(0, "inode %llu, requeue = %d\n", 2779b0697053SMark Fasheh (unsigned long long)OCFS2_I(inode)->ip_blkno, *requeue); 2780ccd979bdSMark Fasheh 2781ccd979bdSMark Fasheh mlog_exit(status); 2782ccd979bdSMark Fasheh return status; 2783ccd979bdSMark Fasheh } 2784ccd979bdSMark Fasheh 2785ccd979bdSMark Fasheh /* Generic unblock function for any lockres whose private data is an 2786ccd979bdSMark Fasheh * ocfs2_super pointer. */ 2787ccd979bdSMark Fasheh static int ocfs2_unblock_osb_lock(struct ocfs2_lock_res *lockres, 2788ccd979bdSMark Fasheh int *requeue) 2789ccd979bdSMark Fasheh { 2790ccd979bdSMark Fasheh int status; 2791ccd979bdSMark Fasheh struct ocfs2_super *osb; 2792ccd979bdSMark Fasheh 2793ccd979bdSMark Fasheh mlog_entry_void(); 2794ccd979bdSMark Fasheh 2795ccd979bdSMark Fasheh mlog(0, "Unblock lockres %s\n", lockres->l_name); 2796ccd979bdSMark Fasheh 2797ccd979bdSMark Fasheh osb = ocfs2_lock_res_super(lockres); 2798ccd979bdSMark Fasheh 2799ccd979bdSMark Fasheh status = ocfs2_generic_unblock_lock(osb, 2800ccd979bdSMark Fasheh lockres, 2801ccd979bdSMark Fasheh requeue, 2802ccd979bdSMark Fasheh NULL); 2803ccd979bdSMark Fasheh if (status < 0) 2804ccd979bdSMark Fasheh mlog_errno(status); 2805ccd979bdSMark Fasheh 2806ccd979bdSMark Fasheh mlog_exit(status); 2807ccd979bdSMark Fasheh return status; 2808ccd979bdSMark Fasheh } 2809ccd979bdSMark Fasheh 2810ccd979bdSMark Fasheh void ocfs2_process_blocked_lock(struct ocfs2_super *osb, 2811ccd979bdSMark Fasheh struct ocfs2_lock_res *lockres) 2812ccd979bdSMark Fasheh { 2813ccd979bdSMark Fasheh int status; 2814ccd979bdSMark Fasheh int requeue = 0; 2815ccd979bdSMark Fasheh unsigned long flags; 2816ccd979bdSMark Fasheh 2817ccd979bdSMark Fasheh /* Our reference to the lockres in this function can be 2818ccd979bdSMark Fasheh * considered valid until we remove the OCFS2_LOCK_QUEUED 2819ccd979bdSMark Fasheh * flag. */ 2820ccd979bdSMark Fasheh 2821ccd979bdSMark Fasheh mlog_entry_void(); 2822ccd979bdSMark Fasheh 2823ccd979bdSMark Fasheh BUG_ON(!lockres); 2824ccd979bdSMark Fasheh BUG_ON(!lockres->l_ops); 2825ccd979bdSMark Fasheh BUG_ON(!lockres->l_ops->unblock); 2826ccd979bdSMark Fasheh 2827ccd979bdSMark Fasheh mlog(0, "lockres %s blocked.\n", lockres->l_name); 2828ccd979bdSMark Fasheh 2829ccd979bdSMark Fasheh /* Detect whether a lock has been marked as going away while 2830ccd979bdSMark Fasheh * the vote thread was processing other things. A lock can 2831ccd979bdSMark Fasheh * still be marked with OCFS2_LOCK_FREEING after this check, 2832ccd979bdSMark Fasheh * but short circuiting here will still save us some 2833ccd979bdSMark Fasheh * performance. */ 2834ccd979bdSMark Fasheh spin_lock_irqsave(&lockres->l_lock, flags); 2835ccd979bdSMark Fasheh if (lockres->l_flags & OCFS2_LOCK_FREEING) 2836ccd979bdSMark Fasheh goto unqueue; 2837ccd979bdSMark Fasheh spin_unlock_irqrestore(&lockres->l_lock, flags); 2838ccd979bdSMark Fasheh 2839ccd979bdSMark Fasheh status = lockres->l_ops->unblock(lockres, &requeue); 2840ccd979bdSMark Fasheh if (status < 0) 2841ccd979bdSMark Fasheh mlog_errno(status); 2842ccd979bdSMark Fasheh 2843ccd979bdSMark Fasheh spin_lock_irqsave(&lockres->l_lock, flags); 2844ccd979bdSMark Fasheh unqueue: 2845ccd979bdSMark Fasheh if (lockres->l_flags & OCFS2_LOCK_FREEING || !requeue) { 2846ccd979bdSMark Fasheh lockres_clear_flags(lockres, OCFS2_LOCK_QUEUED); 2847ccd979bdSMark Fasheh } else 2848ccd979bdSMark Fasheh ocfs2_schedule_blocked_lock(osb, lockres); 2849ccd979bdSMark Fasheh 2850ccd979bdSMark Fasheh mlog(0, "lockres %s, requeue = %s.\n", lockres->l_name, 2851ccd979bdSMark Fasheh requeue ? "yes" : "no"); 2852ccd979bdSMark Fasheh spin_unlock_irqrestore(&lockres->l_lock, flags); 2853ccd979bdSMark Fasheh 2854ccd979bdSMark Fasheh mlog_exit_void(); 2855ccd979bdSMark Fasheh } 2856ccd979bdSMark Fasheh 2857ccd979bdSMark Fasheh static void ocfs2_schedule_blocked_lock(struct ocfs2_super *osb, 2858ccd979bdSMark Fasheh struct ocfs2_lock_res *lockres) 2859ccd979bdSMark Fasheh { 2860ccd979bdSMark Fasheh mlog_entry_void(); 2861ccd979bdSMark Fasheh 2862ccd979bdSMark Fasheh assert_spin_locked(&lockres->l_lock); 2863ccd979bdSMark Fasheh 2864ccd979bdSMark Fasheh if (lockres->l_flags & OCFS2_LOCK_FREEING) { 2865ccd979bdSMark Fasheh /* Do not schedule a lock for downconvert when it's on 2866ccd979bdSMark Fasheh * the way to destruction - any nodes wanting access 2867ccd979bdSMark Fasheh * to the resource will get it soon. */ 2868ccd979bdSMark Fasheh mlog(0, "Lockres %s won't be scheduled: flags 0x%lx\n", 2869ccd979bdSMark Fasheh lockres->l_name, lockres->l_flags); 2870ccd979bdSMark Fasheh return; 2871ccd979bdSMark Fasheh } 2872ccd979bdSMark Fasheh 2873ccd979bdSMark Fasheh lockres_or_flags(lockres, OCFS2_LOCK_QUEUED); 2874ccd979bdSMark Fasheh 2875ccd979bdSMark Fasheh spin_lock(&osb->vote_task_lock); 2876ccd979bdSMark Fasheh if (list_empty(&lockres->l_blocked_list)) { 2877ccd979bdSMark Fasheh list_add_tail(&lockres->l_blocked_list, 2878ccd979bdSMark Fasheh &osb->blocked_lock_list); 2879ccd979bdSMark Fasheh osb->blocked_lock_count++; 2880ccd979bdSMark Fasheh } 2881ccd979bdSMark Fasheh spin_unlock(&osb->vote_task_lock); 2882ccd979bdSMark Fasheh 2883ccd979bdSMark Fasheh mlog_exit_void(); 2884ccd979bdSMark Fasheh } 2885ccd979bdSMark Fasheh 2886ccd979bdSMark Fasheh /* This aids in debugging situations where a bad LVB might be involved. */ 2887ccd979bdSMark Fasheh void ocfs2_dump_meta_lvb_info(u64 level, 2888ccd979bdSMark Fasheh const char *function, 2889ccd979bdSMark Fasheh unsigned int line, 2890ccd979bdSMark Fasheh struct ocfs2_lock_res *lockres) 2891ccd979bdSMark Fasheh { 2892ccd979bdSMark Fasheh struct ocfs2_meta_lvb *lvb = (struct ocfs2_meta_lvb *) lockres->l_lksb.lvb; 2893ccd979bdSMark Fasheh 2894ccd979bdSMark Fasheh mlog(level, "LVB information for %s (called from %s:%u):\n", 2895ccd979bdSMark Fasheh lockres->l_name, function, line); 2896ccd979bdSMark Fasheh mlog(level, "version: %u, clusters: %u\n", 2897ccd979bdSMark Fasheh be32_to_cpu(lvb->lvb_version), be32_to_cpu(lvb->lvb_iclusters)); 2898b0697053SMark Fasheh mlog(level, "size: %llu, uid %u, gid %u, mode 0x%x\n", 2899b0697053SMark Fasheh (unsigned long long)be64_to_cpu(lvb->lvb_isize), 2900b0697053SMark Fasheh be32_to_cpu(lvb->lvb_iuid), be32_to_cpu(lvb->lvb_igid), 2901b0697053SMark Fasheh be16_to_cpu(lvb->lvb_imode)); 2902b0697053SMark Fasheh mlog(level, "nlink %u, atime_packed 0x%llx, ctime_packed 0x%llx, " 2903b0697053SMark Fasheh "mtime_packed 0x%llx\n", be16_to_cpu(lvb->lvb_inlink), 2904b0697053SMark Fasheh (long long)be64_to_cpu(lvb->lvb_iatime_packed), 2905b0697053SMark Fasheh (long long)be64_to_cpu(lvb->lvb_ictime_packed), 2906b0697053SMark Fasheh (long long)be64_to_cpu(lvb->lvb_imtime_packed)); 2907ccd979bdSMark Fasheh } 2908