18df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh/* -*- mode: c; c-basic-offset: 8; -*- 28df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh * vim: noexpandtab sw=8 ts=8 sts=0: 38df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh * 48df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh * userdlm.c 58df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh * 68df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh * Code which implements the kernel side of a minimal userspace 78df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh * interface to our DLM. 88df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh * 98df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh * Many of the functions here are pared down versions of dlmglue.c 108df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh * functions. 118df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh * 128df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh * Copyright (C) 2003, 2004 Oracle. All rights reserved. 138df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh * 148df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh * This program is free software; you can redistribute it and/or 158df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh * modify it under the terms of the GNU General Public 168df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh * License as published by the Free Software Foundation; either 178df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh * version 2 of the License, or (at your option) any later version. 188df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh * 198df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh * This program is distributed in the hope that it will be useful, 208df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh * but WITHOUT ANY WARRANTY; without even the implied warranty of 218df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 228df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh * General Public License for more details. 238df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh * 248df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh * You should have received a copy of the GNU General Public 258df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh * License along with this program; if not, write to the 268df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh * Free Software Foundation, Inc., 59 Temple Place - Suite 330, 278df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh * Boston, MA 021110-1307, USA. 288df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh */ 298df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 30aee93ac4b7ad461255939248d0d51566cff77e05Jeff Mahoney#include <linux/signal.h> 318df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 328df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh#include <linux/module.h> 338df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh#include <linux/fs.h> 348df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh#include <linux/types.h> 358df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh#include <linux/crc32.h> 368df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 370016eedc4185a3cd7e578b027a6e69001b85d6c4Joel Becker#include "ocfs2_lockingver.h" 380016eedc4185a3cd7e578b027a6e69001b85d6c4Joel Becker#include "stackglue.h" 398df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh#include "userdlm.h" 408df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 418df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh#define MLOG_MASK_PREFIX ML_DLMFS 428df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh#include "cluster/masklog.h" 438df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 440016eedc4185a3cd7e578b027a6e69001b85d6c4Joel Becker 450016eedc4185a3cd7e578b027a6e69001b85d6c4Joel Beckerstatic inline struct user_lock_res *user_lksb_to_lock_res(struct ocfs2_dlm_lksb *lksb) 460016eedc4185a3cd7e578b027a6e69001b85d6c4Joel Becker{ 470016eedc4185a3cd7e578b027a6e69001b85d6c4Joel Becker return container_of(lksb, struct user_lock_res, l_lksb); 480016eedc4185a3cd7e578b027a6e69001b85d6c4Joel Becker} 490016eedc4185a3cd7e578b027a6e69001b85d6c4Joel Becker 508df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fashehstatic inline int user_check_wait_flag(struct user_lock_res *lockres, 518df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh int flag) 528df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh{ 538df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh int ret; 548df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 558df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh spin_lock(&lockres->l_lock); 568df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh ret = lockres->l_flags & flag; 578df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh spin_unlock(&lockres->l_lock); 588df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 598df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh return ret; 608df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh} 618df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 628df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fashehstatic inline void user_wait_on_busy_lock(struct user_lock_res *lockres) 638df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 648df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh{ 658df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh wait_event(lockres->l_event, 668df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh !user_check_wait_flag(lockres, USER_LOCK_BUSY)); 678df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh} 688df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 698df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fashehstatic inline void user_wait_on_blocked_lock(struct user_lock_res *lockres) 708df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 718df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh{ 728df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh wait_event(lockres->l_event, 738df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh !user_check_wait_flag(lockres, USER_LOCK_BLOCKED)); 748df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh} 758df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 768df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh/* I heart container_of... */ 770016eedc4185a3cd7e578b027a6e69001b85d6c4Joel Beckerstatic inline struct ocfs2_cluster_connection * 780016eedc4185a3cd7e578b027a6e69001b85d6c4Joel Beckercluster_connection_from_user_lockres(struct user_lock_res *lockres) 798df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh{ 808df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh struct dlmfs_inode_private *ip; 818df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 828df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh ip = container_of(lockres, 838df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh struct dlmfs_inode_private, 848df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh ip_lockres); 850016eedc4185a3cd7e578b027a6e69001b85d6c4Joel Becker return ip->ip_conn; 868df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh} 878df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 888df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fashehstatic struct inode * 898df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fashehuser_dlm_inode_from_user_lockres(struct user_lock_res *lockres) 908df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh{ 918df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh struct dlmfs_inode_private *ip; 928df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 938df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh ip = container_of(lockres, 948df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh struct dlmfs_inode_private, 958df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh ip_lockres); 968df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh return &ip->ip_vfs_inode; 978df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh} 988df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 998df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fashehstatic inline void user_recover_from_dlm_error(struct user_lock_res *lockres) 1008df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh{ 1018df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh spin_lock(&lockres->l_lock); 1028df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh lockres->l_flags &= ~USER_LOCK_BUSY; 1038df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh spin_unlock(&lockres->l_lock); 1048df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh} 1058df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 106ea5b3a187e2724fa9d08b2fbd3898c149ed95c6bMark Fasheh#define user_log_dlm_error(_func, _stat, _lockres) do { \ 1070016eedc4185a3cd7e578b027a6e69001b85d6c4Joel Becker mlog(ML_ERROR, "Dlm error %d while calling %s on " \ 1080016eedc4185a3cd7e578b027a6e69001b85d6c4Joel Becker "resource %.*s\n", _stat, _func, \ 1090016eedc4185a3cd7e578b027a6e69001b85d6c4Joel Becker _lockres->l_namelen, _lockres->l_name); \ 1108df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh} while (0) 1118df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 1128df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh/* WARNING: This function lives in a world where the only three lock 1138df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh * levels are EX, PR, and NL. It *will* have to be adjusted when more 1148df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh * lock types are added. */ 1158df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fashehstatic inline int user_highest_compat_lock_level(int level) 1168df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh{ 1170016eedc4185a3cd7e578b027a6e69001b85d6c4Joel Becker int new_level = DLM_LOCK_EX; 1188df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 1190016eedc4185a3cd7e578b027a6e69001b85d6c4Joel Becker if (level == DLM_LOCK_EX) 1200016eedc4185a3cd7e578b027a6e69001b85d6c4Joel Becker new_level = DLM_LOCK_NL; 1210016eedc4185a3cd7e578b027a6e69001b85d6c4Joel Becker else if (level == DLM_LOCK_PR) 1220016eedc4185a3cd7e578b027a6e69001b85d6c4Joel Becker new_level = DLM_LOCK_PR; 1238df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh return new_level; 1248df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh} 1258df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 1260016eedc4185a3cd7e578b027a6e69001b85d6c4Joel Beckerstatic void user_ast(struct ocfs2_dlm_lksb *lksb) 1278df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh{ 1280016eedc4185a3cd7e578b027a6e69001b85d6c4Joel Becker struct user_lock_res *lockres = user_lksb_to_lock_res(lksb); 1290016eedc4185a3cd7e578b027a6e69001b85d6c4Joel Becker int status; 1308df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 1316fcef3f04a1a0f8d7a086147d2f2e650c8cc2754Sunil Mushran mlog(ML_BASTS, "AST fired for lockres %.*s, level %d => %d\n", 1326fcef3f04a1a0f8d7a086147d2f2e650c8cc2754Sunil Mushran lockres->l_namelen, lockres->l_name, lockres->l_level, 1336fcef3f04a1a0f8d7a086147d2f2e650c8cc2754Sunil Mushran lockres->l_requested); 1348df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 1358df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh spin_lock(&lockres->l_lock); 1368df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 1370016eedc4185a3cd7e578b027a6e69001b85d6c4Joel Becker status = ocfs2_dlm_lock_status(&lockres->l_lksb); 1380016eedc4185a3cd7e578b027a6e69001b85d6c4Joel Becker if (status) { 139ea5b3a187e2724fa9d08b2fbd3898c149ed95c6bMark Fasheh mlog(ML_ERROR, "lksb status value of %u on lockres %.*s\n", 1400016eedc4185a3cd7e578b027a6e69001b85d6c4Joel Becker status, lockres->l_namelen, lockres->l_name); 1418df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh spin_unlock(&lockres->l_lock); 1428df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh return; 1438df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh } 1448df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 1450016eedc4185a3cd7e578b027a6e69001b85d6c4Joel Becker mlog_bug_on_msg(lockres->l_requested == DLM_LOCK_IV, 146ea5b3a187e2724fa9d08b2fbd3898c149ed95c6bMark Fasheh "Lockres %.*s, requested ivmode. flags 0x%x\n", 147ea5b3a187e2724fa9d08b2fbd3898c149ed95c6bMark Fasheh lockres->l_namelen, lockres->l_name, lockres->l_flags); 148cc6eb725955efb026007e1d7da8fe5383981afd2Mark Fasheh 1498df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh /* we're downconverting. */ 1508df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh if (lockres->l_requested < lockres->l_level) { 1518df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh if (lockres->l_requested <= 1528df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh user_highest_compat_lock_level(lockres->l_blocking)) { 1530016eedc4185a3cd7e578b027a6e69001b85d6c4Joel Becker lockres->l_blocking = DLM_LOCK_NL; 1548df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh lockres->l_flags &= ~USER_LOCK_BLOCKED; 1558df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh } 1568df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh } 1578df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 1588df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh lockres->l_level = lockres->l_requested; 1590016eedc4185a3cd7e578b027a6e69001b85d6c4Joel Becker lockres->l_requested = DLM_LOCK_IV; 1608df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh lockres->l_flags |= USER_LOCK_ATTACHED; 1618df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh lockres->l_flags &= ~USER_LOCK_BUSY; 1628df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 1638df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh spin_unlock(&lockres->l_lock); 1648df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 1658df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh wake_up(&lockres->l_event); 1668df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh} 1678df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 1688df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fashehstatic inline void user_dlm_grab_inode_ref(struct user_lock_res *lockres) 1698df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh{ 1708df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh struct inode *inode; 1718df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh inode = user_dlm_inode_from_user_lockres(lockres); 1728df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh if (!igrab(inode)) 1738df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh BUG(); 1748df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh} 1758df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 176c4028958b6ecad064b1a6303a6a5906d4fe48d73David Howellsstatic void user_dlm_unblock_lock(struct work_struct *work); 1778df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 1788df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fashehstatic void __user_dlm_queue_lockres(struct user_lock_res *lockres) 1798df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh{ 1808df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh if (!(lockres->l_flags & USER_LOCK_QUEUED)) { 1818df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh user_dlm_grab_inode_ref(lockres); 1828df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 183c4028958b6ecad064b1a6303a6a5906d4fe48d73David Howells INIT_WORK(&lockres->l_work, user_dlm_unblock_lock); 1848df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 1858df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh queue_work(user_dlm_worker, &lockres->l_work); 1868df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh lockres->l_flags |= USER_LOCK_QUEUED; 1878df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh } 1888df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh} 1898df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 1908df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fashehstatic void __user_dlm_cond_queue_lockres(struct user_lock_res *lockres) 1918df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh{ 1928df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh int queue = 0; 1938df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 1948df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh if (!(lockres->l_flags & USER_LOCK_BLOCKED)) 1958df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh return; 1968df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 1978df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh switch (lockres->l_blocking) { 1980016eedc4185a3cd7e578b027a6e69001b85d6c4Joel Becker case DLM_LOCK_EX: 1998df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh if (!lockres->l_ex_holders && !lockres->l_ro_holders) 2008df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh queue = 1; 2018df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh break; 2020016eedc4185a3cd7e578b027a6e69001b85d6c4Joel Becker case DLM_LOCK_PR: 2038df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh if (!lockres->l_ex_holders) 2048df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh queue = 1; 2058df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh break; 2068df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh default: 2078df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh BUG(); 2088df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh } 2098df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 2108df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh if (queue) 2118df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh __user_dlm_queue_lockres(lockres); 2128df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh} 2138df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 2140016eedc4185a3cd7e578b027a6e69001b85d6c4Joel Beckerstatic void user_bast(struct ocfs2_dlm_lksb *lksb, int level) 2158df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh{ 2160016eedc4185a3cd7e578b027a6e69001b85d6c4Joel Becker struct user_lock_res *lockres = user_lksb_to_lock_res(lksb); 2178df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 2186fcef3f04a1a0f8d7a086147d2f2e650c8cc2754Sunil Mushran mlog(ML_BASTS, "BAST fired for lockres %.*s, blocking %d, level %d\n", 2196fcef3f04a1a0f8d7a086147d2f2e650c8cc2754Sunil Mushran lockres->l_namelen, lockres->l_name, level, lockres->l_level); 2208df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 2218df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh spin_lock(&lockres->l_lock); 2228df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh lockres->l_flags |= USER_LOCK_BLOCKED; 2238df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh if (level > lockres->l_blocking) 2248df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh lockres->l_blocking = level; 2258df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 2268df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh __user_dlm_queue_lockres(lockres); 2278df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh spin_unlock(&lockres->l_lock); 2288df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 2298df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh wake_up(&lockres->l_event); 2308df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh} 2318df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 2320016eedc4185a3cd7e578b027a6e69001b85d6c4Joel Beckerstatic void user_unlock_ast(struct ocfs2_dlm_lksb *lksb, int status) 2338df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh{ 2340016eedc4185a3cd7e578b027a6e69001b85d6c4Joel Becker struct user_lock_res *lockres = user_lksb_to_lock_res(lksb); 2358df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 2366fcef3f04a1a0f8d7a086147d2f2e650c8cc2754Sunil Mushran mlog(ML_BASTS, "UNLOCK AST fired for lockres %.*s, flags 0x%x\n", 2376fcef3f04a1a0f8d7a086147d2f2e650c8cc2754Sunil Mushran lockres->l_namelen, lockres->l_name, lockres->l_flags); 2388df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 2390016eedc4185a3cd7e578b027a6e69001b85d6c4Joel Becker if (status) 2400016eedc4185a3cd7e578b027a6e69001b85d6c4Joel Becker mlog(ML_ERROR, "dlm returns status %d\n", status); 2418df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 2428df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh spin_lock(&lockres->l_lock); 2432cd9888590c52ac7592e3607d0a3174ccd57ef86Mark Fasheh /* The teardown flag gets set early during the unlock process, 2442cd9888590c52ac7592e3607d0a3174ccd57ef86Mark Fasheh * so test the cancel flag to make sure that this ast isn't 2452cd9888590c52ac7592e3607d0a3174ccd57ef86Mark Fasheh * for a concurrent cancel. */ 2462cd9888590c52ac7592e3607d0a3174ccd57ef86Mark Fasheh if (lockres->l_flags & USER_LOCK_IN_TEARDOWN 2472cd9888590c52ac7592e3607d0a3174ccd57ef86Mark Fasheh && !(lockres->l_flags & USER_LOCK_IN_CANCEL)) { 2480016eedc4185a3cd7e578b027a6e69001b85d6c4Joel Becker lockres->l_level = DLM_LOCK_IV; 2492cd9888590c52ac7592e3607d0a3174ccd57ef86Mark Fasheh } else if (status == DLM_CANCELGRANT) { 250f43e6918c0e3906fd4483316f6a1a07bba615908Mark Fasheh /* We tried to cancel a convert request, but it was 251f43e6918c0e3906fd4483316f6a1a07bba615908Mark Fasheh * already granted. Don't clear the busy flag - the 252f43e6918c0e3906fd4483316f6a1a07bba615908Mark Fasheh * ast should've done this already. */ 253f43e6918c0e3906fd4483316f6a1a07bba615908Mark Fasheh BUG_ON(!(lockres->l_flags & USER_LOCK_IN_CANCEL)); 254f43e6918c0e3906fd4483316f6a1a07bba615908Mark Fasheh lockres->l_flags &= ~USER_LOCK_IN_CANCEL; 255f43e6918c0e3906fd4483316f6a1a07bba615908Mark Fasheh goto out_noclear; 256f43e6918c0e3906fd4483316f6a1a07bba615908Mark Fasheh } else { 257f43e6918c0e3906fd4483316f6a1a07bba615908Mark Fasheh BUG_ON(!(lockres->l_flags & USER_LOCK_IN_CANCEL)); 258f43e6918c0e3906fd4483316f6a1a07bba615908Mark Fasheh /* Cancel succeeded, we want to re-queue */ 2590016eedc4185a3cd7e578b027a6e69001b85d6c4Joel Becker lockres->l_requested = DLM_LOCK_IV; /* cancel an 2608df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh * upconvert 2618df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh * request. */ 2628df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh lockres->l_flags &= ~USER_LOCK_IN_CANCEL; 2638df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh /* we want the unblock thread to look at it again 2648df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh * now. */ 265f43e6918c0e3906fd4483316f6a1a07bba615908Mark Fasheh if (lockres->l_flags & USER_LOCK_BLOCKED) 266f43e6918c0e3906fd4483316f6a1a07bba615908Mark Fasheh __user_dlm_queue_lockres(lockres); 2678df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh } 2688df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 2698df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh lockres->l_flags &= ~USER_LOCK_BUSY; 270f43e6918c0e3906fd4483316f6a1a07bba615908Mark Fashehout_noclear: 2718df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh spin_unlock(&lockres->l_lock); 2728df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 2738df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh wake_up(&lockres->l_event); 2748df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh} 2758df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 2760016eedc4185a3cd7e578b027a6e69001b85d6c4Joel Becker/* 2770016eedc4185a3cd7e578b027a6e69001b85d6c4Joel Becker * This is the userdlmfs locking protocol version. 2780016eedc4185a3cd7e578b027a6e69001b85d6c4Joel Becker * 2790016eedc4185a3cd7e578b027a6e69001b85d6c4Joel Becker * See fs/ocfs2/dlmglue.c for more details on locking versions. 2800016eedc4185a3cd7e578b027a6e69001b85d6c4Joel Becker */ 2810016eedc4185a3cd7e578b027a6e69001b85d6c4Joel Beckerstatic struct ocfs2_locking_protocol user_dlm_lproto = { 2820016eedc4185a3cd7e578b027a6e69001b85d6c4Joel Becker .lp_max_version = { 2830016eedc4185a3cd7e578b027a6e69001b85d6c4Joel Becker .pv_major = OCFS2_LOCKING_PROTOCOL_MAJOR, 2840016eedc4185a3cd7e578b027a6e69001b85d6c4Joel Becker .pv_minor = OCFS2_LOCKING_PROTOCOL_MINOR, 2850016eedc4185a3cd7e578b027a6e69001b85d6c4Joel Becker }, 2860016eedc4185a3cd7e578b027a6e69001b85d6c4Joel Becker .lp_lock_ast = user_ast, 2870016eedc4185a3cd7e578b027a6e69001b85d6c4Joel Becker .lp_blocking_ast = user_bast, 2880016eedc4185a3cd7e578b027a6e69001b85d6c4Joel Becker .lp_unlock_ast = user_unlock_ast, 2890016eedc4185a3cd7e578b027a6e69001b85d6c4Joel Becker}; 2900016eedc4185a3cd7e578b027a6e69001b85d6c4Joel Becker 2918df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fashehstatic inline void user_dlm_drop_inode_ref(struct user_lock_res *lockres) 2928df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh{ 2938df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh struct inode *inode; 2948df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh inode = user_dlm_inode_from_user_lockres(lockres); 2958df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh iput(inode); 2968df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh} 2978df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 298c4028958b6ecad064b1a6303a6a5906d4fe48d73David Howellsstatic void user_dlm_unblock_lock(struct work_struct *work) 2998df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh{ 3008df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh int new_level, status; 301c4028958b6ecad064b1a6303a6a5906d4fe48d73David Howells struct user_lock_res *lockres = 302c4028958b6ecad064b1a6303a6a5906d4fe48d73David Howells container_of(work, struct user_lock_res, l_work); 3030016eedc4185a3cd7e578b027a6e69001b85d6c4Joel Becker struct ocfs2_cluster_connection *conn = 3040016eedc4185a3cd7e578b027a6e69001b85d6c4Joel Becker cluster_connection_from_user_lockres(lockres); 3058df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 3066fcef3f04a1a0f8d7a086147d2f2e650c8cc2754Sunil Mushran mlog(0, "lockres %.*s\n", lockres->l_namelen, lockres->l_name); 3078df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 3088df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh spin_lock(&lockres->l_lock); 3098df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 3101f7bc828e30fe3e23ea0968b9595ad20e2785978Mark Fasheh mlog_bug_on_msg(!(lockres->l_flags & USER_LOCK_QUEUED), 311ea5b3a187e2724fa9d08b2fbd3898c149ed95c6bMark Fasheh "Lockres %.*s, flags 0x%x\n", 312ea5b3a187e2724fa9d08b2fbd3898c149ed95c6bMark Fasheh lockres->l_namelen, lockres->l_name, lockres->l_flags); 3138df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 3141f7bc828e30fe3e23ea0968b9595ad20e2785978Mark Fasheh /* notice that we don't clear USER_LOCK_BLOCKED here. If it's 3151f7bc828e30fe3e23ea0968b9595ad20e2785978Mark Fasheh * set, we want user_ast clear it. */ 3168df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh lockres->l_flags &= ~USER_LOCK_QUEUED; 3178df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 3181f7bc828e30fe3e23ea0968b9595ad20e2785978Mark Fasheh /* It's valid to get here and no longer be blocked - if we get 3191f7bc828e30fe3e23ea0968b9595ad20e2785978Mark Fasheh * several basts in a row, we might be queued by the first 3201f7bc828e30fe3e23ea0968b9595ad20e2785978Mark Fasheh * one, the unblock thread might run and clear the queued 3211f7bc828e30fe3e23ea0968b9595ad20e2785978Mark Fasheh * flag, and finally we might get another bast which re-queues 3221f7bc828e30fe3e23ea0968b9595ad20e2785978Mark Fasheh * us before our ast for the downconvert is called. */ 3231f7bc828e30fe3e23ea0968b9595ad20e2785978Mark Fasheh if (!(lockres->l_flags & USER_LOCK_BLOCKED)) { 3246fcef3f04a1a0f8d7a086147d2f2e650c8cc2754Sunil Mushran mlog(ML_BASTS, "lockres %.*s USER_LOCK_BLOCKED\n", 3256fcef3f04a1a0f8d7a086147d2f2e650c8cc2754Sunil Mushran lockres->l_namelen, lockres->l_name); 3261f7bc828e30fe3e23ea0968b9595ad20e2785978Mark Fasheh spin_unlock(&lockres->l_lock); 3271f7bc828e30fe3e23ea0968b9595ad20e2785978Mark Fasheh goto drop_ref; 3281f7bc828e30fe3e23ea0968b9595ad20e2785978Mark Fasheh } 3291f7bc828e30fe3e23ea0968b9595ad20e2785978Mark Fasheh 3308df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh if (lockres->l_flags & USER_LOCK_IN_TEARDOWN) { 3316fcef3f04a1a0f8d7a086147d2f2e650c8cc2754Sunil Mushran mlog(ML_BASTS, "lockres %.*s USER_LOCK_IN_TEARDOWN\n", 3326fcef3f04a1a0f8d7a086147d2f2e650c8cc2754Sunil Mushran lockres->l_namelen, lockres->l_name); 3338df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh spin_unlock(&lockres->l_lock); 3348df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh goto drop_ref; 3358df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh } 3368df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 3378df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh if (lockres->l_flags & USER_LOCK_BUSY) { 3388df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh if (lockres->l_flags & USER_LOCK_IN_CANCEL) { 3396fcef3f04a1a0f8d7a086147d2f2e650c8cc2754Sunil Mushran mlog(ML_BASTS, "lockres %.*s USER_LOCK_IN_CANCEL\n", 3406fcef3f04a1a0f8d7a086147d2f2e650c8cc2754Sunil Mushran lockres->l_namelen, lockres->l_name); 3418df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh spin_unlock(&lockres->l_lock); 3428df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh goto drop_ref; 3438df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh } 3448df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 3458df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh lockres->l_flags |= USER_LOCK_IN_CANCEL; 3468df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh spin_unlock(&lockres->l_lock); 3478df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 3480016eedc4185a3cd7e578b027a6e69001b85d6c4Joel Becker status = ocfs2_dlm_unlock(conn, &lockres->l_lksb, 3490016eedc4185a3cd7e578b027a6e69001b85d6c4Joel Becker DLM_LKF_CANCEL); 3500016eedc4185a3cd7e578b027a6e69001b85d6c4Joel Becker if (status) 3510016eedc4185a3cd7e578b027a6e69001b85d6c4Joel Becker user_log_dlm_error("ocfs2_dlm_unlock", status, lockres); 3528df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh goto drop_ref; 3538df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh } 3548df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 3558df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh /* If there are still incompat holders, we can exit safely 3568df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh * without worrying about re-queueing this lock as that will 3578df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh * happen on the last call to user_cluster_unlock. */ 3580016eedc4185a3cd7e578b027a6e69001b85d6c4Joel Becker if ((lockres->l_blocking == DLM_LOCK_EX) 3598df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh && (lockres->l_ex_holders || lockres->l_ro_holders)) { 3608df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh spin_unlock(&lockres->l_lock); 3616fcef3f04a1a0f8d7a086147d2f2e650c8cc2754Sunil Mushran mlog(ML_BASTS, "lockres %.*s, EX/PR Holders %u,%u\n", 3626fcef3f04a1a0f8d7a086147d2f2e650c8cc2754Sunil Mushran lockres->l_namelen, lockres->l_name, 3636fcef3f04a1a0f8d7a086147d2f2e650c8cc2754Sunil Mushran lockres->l_ex_holders, lockres->l_ro_holders); 3648df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh goto drop_ref; 3658df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh } 3668df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 3670016eedc4185a3cd7e578b027a6e69001b85d6c4Joel Becker if ((lockres->l_blocking == DLM_LOCK_PR) 3688df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh && lockres->l_ex_holders) { 3698df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh spin_unlock(&lockres->l_lock); 3706fcef3f04a1a0f8d7a086147d2f2e650c8cc2754Sunil Mushran mlog(ML_BASTS, "lockres %.*s, EX Holders %u\n", 3716fcef3f04a1a0f8d7a086147d2f2e650c8cc2754Sunil Mushran lockres->l_namelen, lockres->l_name, 3726fcef3f04a1a0f8d7a086147d2f2e650c8cc2754Sunil Mushran lockres->l_ex_holders); 3738df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh goto drop_ref; 3748df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh } 3758df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 3768df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh /* yay, we can downconvert now. */ 3778df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh new_level = user_highest_compat_lock_level(lockres->l_blocking); 3788df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh lockres->l_requested = new_level; 3798df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh lockres->l_flags |= USER_LOCK_BUSY; 3806fcef3f04a1a0f8d7a086147d2f2e650c8cc2754Sunil Mushran mlog(ML_BASTS, "lockres %.*s, downconvert %d => %d\n", 3816fcef3f04a1a0f8d7a086147d2f2e650c8cc2754Sunil Mushran lockres->l_namelen, lockres->l_name, lockres->l_level, new_level); 3828df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh spin_unlock(&lockres->l_lock); 3838df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 3848df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh /* need lock downconvert request now... */ 3850016eedc4185a3cd7e578b027a6e69001b85d6c4Joel Becker status = ocfs2_dlm_lock(conn, new_level, &lockres->l_lksb, 3860016eedc4185a3cd7e578b027a6e69001b85d6c4Joel Becker DLM_LKF_CONVERT|DLM_LKF_VALBLK, 3870016eedc4185a3cd7e578b027a6e69001b85d6c4Joel Becker lockres->l_name, 3880016eedc4185a3cd7e578b027a6e69001b85d6c4Joel Becker lockres->l_namelen); 3890016eedc4185a3cd7e578b027a6e69001b85d6c4Joel Becker if (status) { 3900016eedc4185a3cd7e578b027a6e69001b85d6c4Joel Becker user_log_dlm_error("ocfs2_dlm_lock", status, lockres); 3918df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh user_recover_from_dlm_error(lockres); 3928df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh } 3938df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 3948df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fashehdrop_ref: 3958df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh user_dlm_drop_inode_ref(lockres); 3968df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh} 3978df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 3988df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fashehstatic inline void user_dlm_inc_holders(struct user_lock_res *lockres, 3998df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh int level) 4008df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh{ 4018df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh switch(level) { 4020016eedc4185a3cd7e578b027a6e69001b85d6c4Joel Becker case DLM_LOCK_EX: 4038df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh lockres->l_ex_holders++; 4048df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh break; 4050016eedc4185a3cd7e578b027a6e69001b85d6c4Joel Becker case DLM_LOCK_PR: 4068df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh lockres->l_ro_holders++; 4078df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh break; 4088df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh default: 4098df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh BUG(); 4108df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh } 4118df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh} 4128df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 4138df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh/* predict what lock level we'll be dropping down to on behalf 4148df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh * of another node, and return true if the currently wanted 4158df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh * level will be compatible with it. */ 4168df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fashehstatic inline int 4178df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fashehuser_may_continue_on_blocked_lock(struct user_lock_res *lockres, 4188df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh int wanted) 4198df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh{ 4208df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh BUG_ON(!(lockres->l_flags & USER_LOCK_BLOCKED)); 4218df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 4228df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh return wanted <= user_highest_compat_lock_level(lockres->l_blocking); 4238df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh} 4248df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 4258df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fashehint user_dlm_cluster_lock(struct user_lock_res *lockres, 4268df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh int level, 4278df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh int lkm_flags) 4288df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh{ 4298df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh int status, local_flags; 4300016eedc4185a3cd7e578b027a6e69001b85d6c4Joel Becker struct ocfs2_cluster_connection *conn = 4310016eedc4185a3cd7e578b027a6e69001b85d6c4Joel Becker cluster_connection_from_user_lockres(lockres); 4328df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 4330016eedc4185a3cd7e578b027a6e69001b85d6c4Joel Becker if (level != DLM_LOCK_EX && 4340016eedc4185a3cd7e578b027a6e69001b85d6c4Joel Becker level != DLM_LOCK_PR) { 435ea5b3a187e2724fa9d08b2fbd3898c149ed95c6bMark Fasheh mlog(ML_ERROR, "lockres %.*s: invalid request!\n", 436ea5b3a187e2724fa9d08b2fbd3898c149ed95c6bMark Fasheh lockres->l_namelen, lockres->l_name); 4378df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh status = -EINVAL; 4388df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh goto bail; 4398df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh } 4408df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 4416fcef3f04a1a0f8d7a086147d2f2e650c8cc2754Sunil Mushran mlog(ML_BASTS, "lockres %.*s, level %d, flags = 0x%x\n", 4426fcef3f04a1a0f8d7a086147d2f2e650c8cc2754Sunil Mushran lockres->l_namelen, lockres->l_name, level, lkm_flags); 4438df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 4448df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fashehagain: 4458df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh if (signal_pending(current)) { 4468df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh status = -ERESTARTSYS; 4478df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh goto bail; 4488df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh } 4498df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 4508df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh spin_lock(&lockres->l_lock); 4518df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 4528df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh /* We only compare against the currently granted level 4538df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh * here. If the lock is blocked waiting on a downconvert, 4548df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh * we'll get caught below. */ 4558df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh if ((lockres->l_flags & USER_LOCK_BUSY) && 4568df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh (level > lockres->l_level)) { 4578df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh /* is someone sitting in dlm_lock? If so, wait on 4588df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh * them. */ 4598df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh spin_unlock(&lockres->l_lock); 4608df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 4618df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh user_wait_on_busy_lock(lockres); 4628df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh goto again; 4638df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh } 4648df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 4658df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh if ((lockres->l_flags & USER_LOCK_BLOCKED) && 4668df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh (!user_may_continue_on_blocked_lock(lockres, level))) { 4678df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh /* is the lock is currently blocked on behalf of 4688df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh * another node */ 4698df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh spin_unlock(&lockres->l_lock); 4708df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 4718df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh user_wait_on_blocked_lock(lockres); 4728df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh goto again; 4738df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh } 4748df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 4758df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh if (level > lockres->l_level) { 4760016eedc4185a3cd7e578b027a6e69001b85d6c4Joel Becker local_flags = lkm_flags | DLM_LKF_VALBLK; 4770016eedc4185a3cd7e578b027a6e69001b85d6c4Joel Becker if (lockres->l_level != DLM_LOCK_IV) 4780016eedc4185a3cd7e578b027a6e69001b85d6c4Joel Becker local_flags |= DLM_LKF_CONVERT; 4798df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 4808df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh lockres->l_requested = level; 4818df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh lockres->l_flags |= USER_LOCK_BUSY; 4828df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh spin_unlock(&lockres->l_lock); 4838df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 4840016eedc4185a3cd7e578b027a6e69001b85d6c4Joel Becker BUG_ON(level == DLM_LOCK_IV); 4850016eedc4185a3cd7e578b027a6e69001b85d6c4Joel Becker BUG_ON(level == DLM_LOCK_NL); 4868df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 4878df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh /* call dlm_lock to upgrade lock now */ 4880016eedc4185a3cd7e578b027a6e69001b85d6c4Joel Becker status = ocfs2_dlm_lock(conn, level, &lockres->l_lksb, 4890016eedc4185a3cd7e578b027a6e69001b85d6c4Joel Becker local_flags, lockres->l_name, 4900016eedc4185a3cd7e578b027a6e69001b85d6c4Joel Becker lockres->l_namelen); 4910016eedc4185a3cd7e578b027a6e69001b85d6c4Joel Becker if (status) { 4920016eedc4185a3cd7e578b027a6e69001b85d6c4Joel Becker if ((lkm_flags & DLM_LKF_NOQUEUE) && 4930016eedc4185a3cd7e578b027a6e69001b85d6c4Joel Becker (status != -EAGAIN)) 4940016eedc4185a3cd7e578b027a6e69001b85d6c4Joel Becker user_log_dlm_error("ocfs2_dlm_lock", 4950016eedc4185a3cd7e578b027a6e69001b85d6c4Joel Becker status, lockres); 4968df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh user_recover_from_dlm_error(lockres); 4978df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh goto bail; 4988df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh } 4998df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 5008df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh user_wait_on_busy_lock(lockres); 5018df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh goto again; 5028df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh } 5038df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 5048df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh user_dlm_inc_holders(lockres, level); 5058df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh spin_unlock(&lockres->l_lock); 5068df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 5078df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh status = 0; 5088df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fashehbail: 5098df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh return status; 5108df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh} 5118df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 5128df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fashehstatic inline void user_dlm_dec_holders(struct user_lock_res *lockres, 5138df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh int level) 5148df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh{ 5158df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh switch(level) { 5160016eedc4185a3cd7e578b027a6e69001b85d6c4Joel Becker case DLM_LOCK_EX: 5178df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh BUG_ON(!lockres->l_ex_holders); 5188df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh lockres->l_ex_holders--; 5198df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh break; 5200016eedc4185a3cd7e578b027a6e69001b85d6c4Joel Becker case DLM_LOCK_PR: 5218df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh BUG_ON(!lockres->l_ro_holders); 5228df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh lockres->l_ro_holders--; 5238df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh break; 5248df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh default: 5258df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh BUG(); 5268df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh } 5278df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh} 5288df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 5298df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fashehvoid user_dlm_cluster_unlock(struct user_lock_res *lockres, 5308df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh int level) 5318df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh{ 5320016eedc4185a3cd7e578b027a6e69001b85d6c4Joel Becker if (level != DLM_LOCK_EX && 5330016eedc4185a3cd7e578b027a6e69001b85d6c4Joel Becker level != DLM_LOCK_PR) { 534ea5b3a187e2724fa9d08b2fbd3898c149ed95c6bMark Fasheh mlog(ML_ERROR, "lockres %.*s: invalid request!\n", 535ea5b3a187e2724fa9d08b2fbd3898c149ed95c6bMark Fasheh lockres->l_namelen, lockres->l_name); 5368df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh return; 5378df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh } 5388df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 5398df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh spin_lock(&lockres->l_lock); 5408df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh user_dlm_dec_holders(lockres, level); 5418df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh __user_dlm_cond_queue_lockres(lockres); 5428df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh spin_unlock(&lockres->l_lock); 5438df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh} 5448df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 5458df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fashehvoid user_dlm_write_lvb(struct inode *inode, 5468df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh const char *val, 5478df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh unsigned int len) 5488df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh{ 5498df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh struct user_lock_res *lockres = &DLMFS_I(inode)->ip_lockres; 5500016eedc4185a3cd7e578b027a6e69001b85d6c4Joel Becker char *lvb; 5518df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 5528df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh BUG_ON(len > DLM_LVB_LEN); 5538df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 5548df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh spin_lock(&lockres->l_lock); 5558df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 5560016eedc4185a3cd7e578b027a6e69001b85d6c4Joel Becker BUG_ON(lockres->l_level < DLM_LOCK_EX); 5570016eedc4185a3cd7e578b027a6e69001b85d6c4Joel Becker lvb = ocfs2_dlm_lvb(&lockres->l_lksb); 5588df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh memcpy(lvb, val, len); 5598df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 5608df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh spin_unlock(&lockres->l_lock); 5618df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh} 5628df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 5630016eedc4185a3cd7e578b027a6e69001b85d6c4Joel Beckerssize_t user_dlm_read_lvb(struct inode *inode, 5640016eedc4185a3cd7e578b027a6e69001b85d6c4Joel Becker char *val, 5650016eedc4185a3cd7e578b027a6e69001b85d6c4Joel Becker unsigned int len) 5668df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh{ 5678df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh struct user_lock_res *lockres = &DLMFS_I(inode)->ip_lockres; 5680016eedc4185a3cd7e578b027a6e69001b85d6c4Joel Becker char *lvb; 5690016eedc4185a3cd7e578b027a6e69001b85d6c4Joel Becker ssize_t ret = len; 5708df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 5718df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh BUG_ON(len > DLM_LVB_LEN); 5728df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 5738df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh spin_lock(&lockres->l_lock); 5748df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 5750016eedc4185a3cd7e578b027a6e69001b85d6c4Joel Becker BUG_ON(lockres->l_level < DLM_LOCK_PR); 5760016eedc4185a3cd7e578b027a6e69001b85d6c4Joel Becker if (ocfs2_dlm_lvb_valid(&lockres->l_lksb)) { 5770016eedc4185a3cd7e578b027a6e69001b85d6c4Joel Becker lvb = ocfs2_dlm_lvb(&lockres->l_lksb); 5780016eedc4185a3cd7e578b027a6e69001b85d6c4Joel Becker memcpy(val, lvb, len); 5790016eedc4185a3cd7e578b027a6e69001b85d6c4Joel Becker } else 5800016eedc4185a3cd7e578b027a6e69001b85d6c4Joel Becker ret = 0; 5818df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 5828df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh spin_unlock(&lockres->l_lock); 5830016eedc4185a3cd7e578b027a6e69001b85d6c4Joel Becker return ret; 5848df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh} 5858df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 5868df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fashehvoid user_dlm_lock_res_init(struct user_lock_res *lockres, 5878df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh struct dentry *dentry) 5888df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh{ 5898df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh memset(lockres, 0, sizeof(*lockres)); 5908df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 5918df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh spin_lock_init(&lockres->l_lock); 5928df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh init_waitqueue_head(&lockres->l_event); 5930016eedc4185a3cd7e578b027a6e69001b85d6c4Joel Becker lockres->l_level = DLM_LOCK_IV; 5940016eedc4185a3cd7e578b027a6e69001b85d6c4Joel Becker lockres->l_requested = DLM_LOCK_IV; 5950016eedc4185a3cd7e578b027a6e69001b85d6c4Joel Becker lockres->l_blocking = DLM_LOCK_IV; 5968df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 5978df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh /* should have been checked before getting here. */ 5988df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh BUG_ON(dentry->d_name.len >= USER_DLM_LOCK_ID_MAX_LEN); 5998df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 6008df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh memcpy(lockres->l_name, 6018df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh dentry->d_name.name, 6028df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh dentry->d_name.len); 603ea5b3a187e2724fa9d08b2fbd3898c149ed95c6bMark Fasheh lockres->l_namelen = dentry->d_name.len; 6048df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh} 6058df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 6068df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fashehint user_dlm_destroy_lock(struct user_lock_res *lockres) 6078df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh{ 6088df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh int status = -EBUSY; 6090016eedc4185a3cd7e578b027a6e69001b85d6c4Joel Becker struct ocfs2_cluster_connection *conn = 6100016eedc4185a3cd7e578b027a6e69001b85d6c4Joel Becker cluster_connection_from_user_lockres(lockres); 6118df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 6126fcef3f04a1a0f8d7a086147d2f2e650c8cc2754Sunil Mushran mlog(ML_BASTS, "lockres %.*s\n", lockres->l_namelen, lockres->l_name); 6138df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 6148df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh spin_lock(&lockres->l_lock); 6152cd9888590c52ac7592e3607d0a3174ccd57ef86Mark Fasheh if (lockres->l_flags & USER_LOCK_IN_TEARDOWN) { 6162cd9888590c52ac7592e3607d0a3174ccd57ef86Mark Fasheh spin_unlock(&lockres->l_lock); 6172cd9888590c52ac7592e3607d0a3174ccd57ef86Mark Fasheh return 0; 6182cd9888590c52ac7592e3607d0a3174ccd57ef86Mark Fasheh } 6192cd9888590c52ac7592e3607d0a3174ccd57ef86Mark Fasheh 6202cd9888590c52ac7592e3607d0a3174ccd57ef86Mark Fasheh lockres->l_flags |= USER_LOCK_IN_TEARDOWN; 6212cd9888590c52ac7592e3607d0a3174ccd57ef86Mark Fasheh 6228df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh while (lockres->l_flags & USER_LOCK_BUSY) { 6238df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh spin_unlock(&lockres->l_lock); 6248df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 6258df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh user_wait_on_busy_lock(lockres); 6268df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 6278df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh spin_lock(&lockres->l_lock); 6288df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh } 6298df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 6308df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh if (lockres->l_ro_holders || lockres->l_ex_holders) { 6318df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh spin_unlock(&lockres->l_lock); 6328df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh goto bail; 6338df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh } 6348df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 6358df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh status = 0; 6368df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh if (!(lockres->l_flags & USER_LOCK_ATTACHED)) { 6378df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh spin_unlock(&lockres->l_lock); 6388df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh goto bail; 6398df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh } 6408df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 6418df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh lockres->l_flags &= ~USER_LOCK_ATTACHED; 6428df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh lockres->l_flags |= USER_LOCK_BUSY; 6438df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh spin_unlock(&lockres->l_lock); 6448df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 6450016eedc4185a3cd7e578b027a6e69001b85d6c4Joel Becker status = ocfs2_dlm_unlock(conn, &lockres->l_lksb, DLM_LKF_VALBLK); 6460016eedc4185a3cd7e578b027a6e69001b85d6c4Joel Becker if (status) { 6470016eedc4185a3cd7e578b027a6e69001b85d6c4Joel Becker user_log_dlm_error("ocfs2_dlm_unlock", status, lockres); 6488df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh goto bail; 6498df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh } 6508df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 6518df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh user_wait_on_busy_lock(lockres); 6528df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 6538df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh status = 0; 6548df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fashehbail: 6558df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh return status; 6568df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh} 6578df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 6580016eedc4185a3cd7e578b027a6e69001b85d6c4Joel Beckerstatic void user_dlm_recovery_handler_noop(int node_num, 6590016eedc4185a3cd7e578b027a6e69001b85d6c4Joel Becker void *recovery_data) 6608df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh{ 6610016eedc4185a3cd7e578b027a6e69001b85d6c4Joel Becker /* We ignore recovery events */ 6620016eedc4185a3cd7e578b027a6e69001b85d6c4Joel Becker return; 6630016eedc4185a3cd7e578b027a6e69001b85d6c4Joel Becker} 6648df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 6650016eedc4185a3cd7e578b027a6e69001b85d6c4Joel Beckervoid user_dlm_set_locking_protocol(void) 6660016eedc4185a3cd7e578b027a6e69001b85d6c4Joel Becker{ 6670016eedc4185a3cd7e578b027a6e69001b85d6c4Joel Becker ocfs2_stack_glue_set_max_proto_version(&user_dlm_lproto.lp_max_version); 6680016eedc4185a3cd7e578b027a6e69001b85d6c4Joel Becker} 6698df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 6700016eedc4185a3cd7e578b027a6e69001b85d6c4Joel Beckerstruct ocfs2_cluster_connection *user_dlm_register(struct qstr *name) 6710016eedc4185a3cd7e578b027a6e69001b85d6c4Joel Becker{ 6720016eedc4185a3cd7e578b027a6e69001b85d6c4Joel Becker int rc; 6730016eedc4185a3cd7e578b027a6e69001b85d6c4Joel Becker struct ocfs2_cluster_connection *conn; 6748df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 675cbe0e331fdbdb256943499358c75bc098a2134c1Joel Becker rc = ocfs2_cluster_connect_agnostic(name->name, name->len, 676cbe0e331fdbdb256943499358c75bc098a2134c1Joel Becker &user_dlm_lproto, 677cbe0e331fdbdb256943499358c75bc098a2134c1Joel Becker user_dlm_recovery_handler_noop, 678cbe0e331fdbdb256943499358c75bc098a2134c1Joel Becker NULL, &conn); 6790016eedc4185a3cd7e578b027a6e69001b85d6c4Joel Becker if (rc) 6800016eedc4185a3cd7e578b027a6e69001b85d6c4Joel Becker mlog_errno(rc); 6818df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 6820016eedc4185a3cd7e578b027a6e69001b85d6c4Joel Becker return rc ? ERR_PTR(rc) : conn; 6838df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh} 6848df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 6850016eedc4185a3cd7e578b027a6e69001b85d6c4Joel Beckervoid user_dlm_unregister(struct ocfs2_cluster_connection *conn) 6868df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh{ 6870016eedc4185a3cd7e578b027a6e69001b85d6c4Joel Becker ocfs2_cluster_disconnect(conn, 0); 6888df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh} 689