userdlm.c revision ea5b3a187e2724fa9d08b2fbd3898c149ed95c6b
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 378df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 388df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh#include "cluster/nodemanager.h" 398df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh#include "cluster/heartbeat.h" 408df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh#include "cluster/tcp.h" 418df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 428df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh#include "dlmapi.h" 438df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 448df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh#include "userdlm.h" 458df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 468df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh#define MLOG_MASK_PREFIX ML_DLMFS 478df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh#include "cluster/masklog.h" 488df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 498df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fashehstatic inline int user_check_wait_flag(struct user_lock_res *lockres, 508df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh int flag) 518df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh{ 528df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh int ret; 538df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 548df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh spin_lock(&lockres->l_lock); 558df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh ret = lockres->l_flags & flag; 568df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh spin_unlock(&lockres->l_lock); 578df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 588df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh return ret; 598df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh} 608df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 618df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fashehstatic inline void user_wait_on_busy_lock(struct user_lock_res *lockres) 628df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 638df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh{ 648df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh wait_event(lockres->l_event, 658df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh !user_check_wait_flag(lockres, USER_LOCK_BUSY)); 668df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh} 678df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 688df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fashehstatic inline void user_wait_on_blocked_lock(struct user_lock_res *lockres) 698df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 708df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh{ 718df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh wait_event(lockres->l_event, 728df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh !user_check_wait_flag(lockres, USER_LOCK_BLOCKED)); 738df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh} 748df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 758df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh/* I heart container_of... */ 768df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fashehstatic inline struct dlm_ctxt * 778df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fashehdlm_ctxt_from_user_lockres(struct user_lock_res *lockres) 788df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh{ 798df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh struct dlmfs_inode_private *ip; 808df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 818df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh ip = container_of(lockres, 828df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh struct dlmfs_inode_private, 838df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh ip_lockres); 848df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh return ip->ip_dlm; 858df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh} 868df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 878df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fashehstatic struct inode * 888df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fashehuser_dlm_inode_from_user_lockres(struct user_lock_res *lockres) 898df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh{ 908df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh struct dlmfs_inode_private *ip; 918df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 928df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh ip = container_of(lockres, 938df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh struct dlmfs_inode_private, 948df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh ip_lockres); 958df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh return &ip->ip_vfs_inode; 968df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh} 978df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 988df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fashehstatic inline void user_recover_from_dlm_error(struct user_lock_res *lockres) 998df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh{ 1008df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh spin_lock(&lockres->l_lock); 1018df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh lockres->l_flags &= ~USER_LOCK_BUSY; 1028df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh spin_unlock(&lockres->l_lock); 1038df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh} 1048df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 105ea5b3a187e2724fa9d08b2fbd3898c149ed95c6bMark Fasheh#define user_log_dlm_error(_func, _stat, _lockres) do { \ 106ea5b3a187e2724fa9d08b2fbd3898c149ed95c6bMark Fasheh mlog(ML_ERROR, "Dlm error \"%s\" while calling %s on " \ 107ea5b3a187e2724fa9d08b2fbd3898c149ed95c6bMark Fasheh "resource %.*s: %s\n", dlm_errname(_stat), _func, \ 108ea5b3a187e2724fa9d08b2fbd3898c149ed95c6bMark Fasheh _lockres->l_namelen, _lockres->l_name, dlm_errmsg(_stat)); \ 1098df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh} while (0) 1108df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 1118df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh/* WARNING: This function lives in a world where the only three lock 1128df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh * levels are EX, PR, and NL. It *will* have to be adjusted when more 1138df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh * lock types are added. */ 1148df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fashehstatic inline int user_highest_compat_lock_level(int level) 1158df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh{ 1168df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh int new_level = LKM_EXMODE; 1178df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 1188df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh if (level == LKM_EXMODE) 1198df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh new_level = LKM_NLMODE; 1208df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh else if (level == LKM_PRMODE) 1218df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh new_level = LKM_PRMODE; 1228df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh return new_level; 1238df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh} 1248df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 1258df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fashehstatic void user_ast(void *opaque) 1268df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh{ 1278df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh struct user_lock_res *lockres = opaque; 1288df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh struct dlm_lockstatus *lksb; 1298df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 130ea5b3a187e2724fa9d08b2fbd3898c149ed95c6bMark Fasheh mlog(0, "AST fired for lockres %.*s\n", lockres->l_namelen, 131ea5b3a187e2724fa9d08b2fbd3898c149ed95c6bMark Fasheh lockres->l_name); 1328df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 1338df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh spin_lock(&lockres->l_lock); 1348df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 1358df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh lksb = &(lockres->l_lksb); 1368df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh if (lksb->status != DLM_NORMAL) { 137ea5b3a187e2724fa9d08b2fbd3898c149ed95c6bMark Fasheh mlog(ML_ERROR, "lksb status value of %u on lockres %.*s\n", 138ea5b3a187e2724fa9d08b2fbd3898c149ed95c6bMark Fasheh lksb->status, lockres->l_namelen, lockres->l_name); 1398df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh spin_unlock(&lockres->l_lock); 1408df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh return; 1418df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh } 1428df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 143cc6eb725955efb026007e1d7da8fe5383981afd2Mark Fasheh mlog_bug_on_msg(lockres->l_requested == LKM_IVMODE, 144ea5b3a187e2724fa9d08b2fbd3898c149ed95c6bMark Fasheh "Lockres %.*s, requested ivmode. flags 0x%x\n", 145ea5b3a187e2724fa9d08b2fbd3898c149ed95c6bMark Fasheh lockres->l_namelen, lockres->l_name, lockres->l_flags); 146cc6eb725955efb026007e1d7da8fe5383981afd2Mark Fasheh 1478df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh /* we're downconverting. */ 1488df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh if (lockres->l_requested < lockres->l_level) { 1498df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh if (lockres->l_requested <= 1508df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh user_highest_compat_lock_level(lockres->l_blocking)) { 1518df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh lockres->l_blocking = LKM_NLMODE; 1528df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh lockres->l_flags &= ~USER_LOCK_BLOCKED; 1538df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh } 1548df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh } 1558df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 1568df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh lockres->l_level = lockres->l_requested; 1578df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh lockres->l_requested = LKM_IVMODE; 1588df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh lockres->l_flags |= USER_LOCK_ATTACHED; 1598df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh lockres->l_flags &= ~USER_LOCK_BUSY; 1608df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 1618df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh spin_unlock(&lockres->l_lock); 1628df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 1638df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh wake_up(&lockres->l_event); 1648df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh} 1658df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 1668df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fashehstatic inline void user_dlm_grab_inode_ref(struct user_lock_res *lockres) 1678df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh{ 1688df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh struct inode *inode; 1698df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh inode = user_dlm_inode_from_user_lockres(lockres); 1708df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh if (!igrab(inode)) 1718df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh BUG(); 1728df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh} 1738df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 1748df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fashehstatic void user_dlm_unblock_lock(void *opaque); 1758df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 1768df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fashehstatic void __user_dlm_queue_lockres(struct user_lock_res *lockres) 1778df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh{ 1788df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh if (!(lockres->l_flags & USER_LOCK_QUEUED)) { 1798df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh user_dlm_grab_inode_ref(lockres); 1808df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 1818df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh INIT_WORK(&lockres->l_work, user_dlm_unblock_lock, 1828df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh lockres); 1838df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 1848df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh queue_work(user_dlm_worker, &lockres->l_work); 1858df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh lockres->l_flags |= USER_LOCK_QUEUED; 1868df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh } 1878df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh} 1888df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 1898df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fashehstatic void __user_dlm_cond_queue_lockres(struct user_lock_res *lockres) 1908df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh{ 1918df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh int queue = 0; 1928df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 1938df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh if (!(lockres->l_flags & USER_LOCK_BLOCKED)) 1948df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh return; 1958df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 1968df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh switch (lockres->l_blocking) { 1978df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh case LKM_EXMODE: 1988df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh if (!lockres->l_ex_holders && !lockres->l_ro_holders) 1998df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh queue = 1; 2008df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh break; 2018df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh case LKM_PRMODE: 2028df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh if (!lockres->l_ex_holders) 2038df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh queue = 1; 2048df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh break; 2058df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh default: 2068df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh BUG(); 2078df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh } 2088df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 2098df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh if (queue) 2108df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh __user_dlm_queue_lockres(lockres); 2118df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh} 2128df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 2138df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fashehstatic void user_bast(void *opaque, int level) 2148df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh{ 2158df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh struct user_lock_res *lockres = opaque; 2168df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 217ea5b3a187e2724fa9d08b2fbd3898c149ed95c6bMark Fasheh mlog(0, "Blocking AST fired for lockres %.*s. Blocking level %d\n", 218ea5b3a187e2724fa9d08b2fbd3898c149ed95c6bMark Fasheh lockres->l_namelen, lockres->l_name, level); 2198df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 2208df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh spin_lock(&lockres->l_lock); 2218df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh lockres->l_flags |= USER_LOCK_BLOCKED; 2228df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh if (level > lockres->l_blocking) 2238df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh lockres->l_blocking = level; 2248df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 2258df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh __user_dlm_queue_lockres(lockres); 2268df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh spin_unlock(&lockres->l_lock); 2278df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 2288df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh wake_up(&lockres->l_event); 2298df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh} 2308df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 2318df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fashehstatic void user_unlock_ast(void *opaque, enum dlm_status status) 2328df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh{ 2338df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh struct user_lock_res *lockres = opaque; 2348df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 235ea5b3a187e2724fa9d08b2fbd3898c149ed95c6bMark Fasheh mlog(0, "UNLOCK AST called on lock %.*s\n", lockres->l_namelen, 236ea5b3a187e2724fa9d08b2fbd3898c149ed95c6bMark Fasheh lockres->l_name); 2378df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 238f43e6918c0e3906fd4483316f6a1a07bba615908Mark Fasheh if (status != DLM_NORMAL && status != DLM_CANCELGRANT) 2398df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh mlog(ML_ERROR, "Dlm returns status %d\n", status); 2408df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 2418df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh spin_lock(&lockres->l_lock); 2422cd9888590c52ac7592e3607d0a3174ccd57ef86Mark Fasheh /* The teardown flag gets set early during the unlock process, 2432cd9888590c52ac7592e3607d0a3174ccd57ef86Mark Fasheh * so test the cancel flag to make sure that this ast isn't 2442cd9888590c52ac7592e3607d0a3174ccd57ef86Mark Fasheh * for a concurrent cancel. */ 2452cd9888590c52ac7592e3607d0a3174ccd57ef86Mark Fasheh if (lockres->l_flags & USER_LOCK_IN_TEARDOWN 2462cd9888590c52ac7592e3607d0a3174ccd57ef86Mark Fasheh && !(lockres->l_flags & USER_LOCK_IN_CANCEL)) { 2478df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh lockres->l_level = LKM_IVMODE; 2482cd9888590c52ac7592e3607d0a3174ccd57ef86Mark Fasheh } else if (status == DLM_CANCELGRANT) { 249f43e6918c0e3906fd4483316f6a1a07bba615908Mark Fasheh /* We tried to cancel a convert request, but it was 250f43e6918c0e3906fd4483316f6a1a07bba615908Mark Fasheh * already granted. Don't clear the busy flag - the 251f43e6918c0e3906fd4483316f6a1a07bba615908Mark Fasheh * ast should've done this already. */ 252f43e6918c0e3906fd4483316f6a1a07bba615908Mark Fasheh BUG_ON(!(lockres->l_flags & USER_LOCK_IN_CANCEL)); 253f43e6918c0e3906fd4483316f6a1a07bba615908Mark Fasheh lockres->l_flags &= ~USER_LOCK_IN_CANCEL; 254f43e6918c0e3906fd4483316f6a1a07bba615908Mark Fasheh goto out_noclear; 255f43e6918c0e3906fd4483316f6a1a07bba615908Mark Fasheh } else { 256f43e6918c0e3906fd4483316f6a1a07bba615908Mark Fasheh BUG_ON(!(lockres->l_flags & USER_LOCK_IN_CANCEL)); 257f43e6918c0e3906fd4483316f6a1a07bba615908Mark Fasheh /* Cancel succeeded, we want to re-queue */ 2588df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh lockres->l_requested = LKM_IVMODE; /* cancel an 2598df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh * upconvert 2608df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh * request. */ 2618df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh lockres->l_flags &= ~USER_LOCK_IN_CANCEL; 2628df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh /* we want the unblock thread to look at it again 2638df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh * now. */ 264f43e6918c0e3906fd4483316f6a1a07bba615908Mark Fasheh if (lockres->l_flags & USER_LOCK_BLOCKED) 265f43e6918c0e3906fd4483316f6a1a07bba615908Mark Fasheh __user_dlm_queue_lockres(lockres); 2668df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh } 2678df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 2688df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh lockres->l_flags &= ~USER_LOCK_BUSY; 269f43e6918c0e3906fd4483316f6a1a07bba615908Mark Fashehout_noclear: 2708df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh spin_unlock(&lockres->l_lock); 2718df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 2728df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh wake_up(&lockres->l_event); 2738df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh} 2748df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 2758df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fashehstatic inline void user_dlm_drop_inode_ref(struct user_lock_res *lockres) 2768df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh{ 2778df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh struct inode *inode; 2788df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh inode = user_dlm_inode_from_user_lockres(lockres); 2798df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh iput(inode); 2808df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh} 2818df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 2828df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fashehstatic void user_dlm_unblock_lock(void *opaque) 2838df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh{ 2848df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh int new_level, status; 2858df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh struct user_lock_res *lockres = (struct user_lock_res *) opaque; 2868df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh struct dlm_ctxt *dlm = dlm_ctxt_from_user_lockres(lockres); 2878df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 288ea5b3a187e2724fa9d08b2fbd3898c149ed95c6bMark Fasheh mlog(0, "processing lockres %.*s\n", lockres->l_namelen, 289ea5b3a187e2724fa9d08b2fbd3898c149ed95c6bMark Fasheh lockres->l_name); 2908df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 2918df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh spin_lock(&lockres->l_lock); 2928df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 2931f7bc828e30fe3e23ea0968b9595ad20e2785978Mark Fasheh mlog_bug_on_msg(!(lockres->l_flags & USER_LOCK_QUEUED), 294ea5b3a187e2724fa9d08b2fbd3898c149ed95c6bMark Fasheh "Lockres %.*s, flags 0x%x\n", 295ea5b3a187e2724fa9d08b2fbd3898c149ed95c6bMark Fasheh lockres->l_namelen, lockres->l_name, lockres->l_flags); 2968df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 2971f7bc828e30fe3e23ea0968b9595ad20e2785978Mark Fasheh /* notice that we don't clear USER_LOCK_BLOCKED here. If it's 2981f7bc828e30fe3e23ea0968b9595ad20e2785978Mark Fasheh * set, we want user_ast clear it. */ 2998df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh lockres->l_flags &= ~USER_LOCK_QUEUED; 3008df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 3011f7bc828e30fe3e23ea0968b9595ad20e2785978Mark Fasheh /* It's valid to get here and no longer be blocked - if we get 3021f7bc828e30fe3e23ea0968b9595ad20e2785978Mark Fasheh * several basts in a row, we might be queued by the first 3031f7bc828e30fe3e23ea0968b9595ad20e2785978Mark Fasheh * one, the unblock thread might run and clear the queued 3041f7bc828e30fe3e23ea0968b9595ad20e2785978Mark Fasheh * flag, and finally we might get another bast which re-queues 3051f7bc828e30fe3e23ea0968b9595ad20e2785978Mark Fasheh * us before our ast for the downconvert is called. */ 3061f7bc828e30fe3e23ea0968b9595ad20e2785978Mark Fasheh if (!(lockres->l_flags & USER_LOCK_BLOCKED)) { 3071f7bc828e30fe3e23ea0968b9595ad20e2785978Mark Fasheh spin_unlock(&lockres->l_lock); 3081f7bc828e30fe3e23ea0968b9595ad20e2785978Mark Fasheh goto drop_ref; 3091f7bc828e30fe3e23ea0968b9595ad20e2785978Mark Fasheh } 3101f7bc828e30fe3e23ea0968b9595ad20e2785978Mark Fasheh 3118df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh if (lockres->l_flags & USER_LOCK_IN_TEARDOWN) { 3128df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh spin_unlock(&lockres->l_lock); 3138df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh goto drop_ref; 3148df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh } 3158df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 3168df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh if (lockres->l_flags & USER_LOCK_BUSY) { 3178df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh if (lockres->l_flags & USER_LOCK_IN_CANCEL) { 3188df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh spin_unlock(&lockres->l_lock); 3198df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh goto drop_ref; 3208df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh } 3218df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 3228df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh lockres->l_flags |= USER_LOCK_IN_CANCEL; 3238df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh spin_unlock(&lockres->l_lock); 3248df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 3258df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh status = dlmunlock(dlm, 3268df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh &lockres->l_lksb, 3278df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh LKM_CANCEL, 3288df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh user_unlock_ast, 3298df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh lockres); 330f43e6918c0e3906fd4483316f6a1a07bba615908Mark Fasheh if (status != DLM_NORMAL) 3318df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh user_log_dlm_error("dlmunlock", status, lockres); 3328df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh goto drop_ref; 3338df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh } 3348df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 3358df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh /* If there are still incompat holders, we can exit safely 3368df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh * without worrying about re-queueing this lock as that will 3378df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh * happen on the last call to user_cluster_unlock. */ 3388df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh if ((lockres->l_blocking == LKM_EXMODE) 3398df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh && (lockres->l_ex_holders || lockres->l_ro_holders)) { 3408df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh spin_unlock(&lockres->l_lock); 3418df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh mlog(0, "can't downconvert for ex: ro = %u, ex = %u\n", 3428df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh lockres->l_ro_holders, lockres->l_ex_holders); 3438df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh goto drop_ref; 3448df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh } 3458df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 3468df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh if ((lockres->l_blocking == LKM_PRMODE) 3478df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh && lockres->l_ex_holders) { 3488df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh spin_unlock(&lockres->l_lock); 3498df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh mlog(0, "can't downconvert for pr: ex = %u\n", 3508df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh lockres->l_ex_holders); 3518df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh goto drop_ref; 3528df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh } 3538df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 3548df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh /* yay, we can downconvert now. */ 3558df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh new_level = user_highest_compat_lock_level(lockres->l_blocking); 3568df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh lockres->l_requested = new_level; 3578df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh lockres->l_flags |= USER_LOCK_BUSY; 3588df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh mlog(0, "Downconvert lock from %d to %d\n", 3598df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh lockres->l_level, new_level); 3608df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh spin_unlock(&lockres->l_lock); 3618df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 3628df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh /* need lock downconvert request now... */ 3638df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh status = dlmlock(dlm, 3648df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh new_level, 3658df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh &lockres->l_lksb, 3668df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh LKM_CONVERT|LKM_VALBLK, 3678df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh lockres->l_name, 368ea5b3a187e2724fa9d08b2fbd3898c149ed95c6bMark Fasheh lockres->l_namelen, 3698df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh user_ast, 3708df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh lockres, 3718df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh user_bast); 3728df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh if (status != DLM_NORMAL) { 3738df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh user_log_dlm_error("dlmlock", status, lockres); 3748df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh user_recover_from_dlm_error(lockres); 3758df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh } 3768df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 3778df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fashehdrop_ref: 3788df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh user_dlm_drop_inode_ref(lockres); 3798df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh} 3808df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 3818df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fashehstatic inline void user_dlm_inc_holders(struct user_lock_res *lockres, 3828df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh int level) 3838df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh{ 3848df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh switch(level) { 3858df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh case LKM_EXMODE: 3868df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh lockres->l_ex_holders++; 3878df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh break; 3888df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh case LKM_PRMODE: 3898df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh lockres->l_ro_holders++; 3908df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh break; 3918df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh default: 3928df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh BUG(); 3938df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh } 3948df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh} 3958df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 3968df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh/* predict what lock level we'll be dropping down to on behalf 3978df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh * of another node, and return true if the currently wanted 3988df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh * level will be compatible with it. */ 3998df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fashehstatic inline int 4008df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fashehuser_may_continue_on_blocked_lock(struct user_lock_res *lockres, 4018df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh int wanted) 4028df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh{ 4038df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh BUG_ON(!(lockres->l_flags & USER_LOCK_BLOCKED)); 4048df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 4058df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh return wanted <= user_highest_compat_lock_level(lockres->l_blocking); 4068df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh} 4078df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 4088df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fashehint user_dlm_cluster_lock(struct user_lock_res *lockres, 4098df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh int level, 4108df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh int lkm_flags) 4118df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh{ 4128df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh int status, local_flags; 4138df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh struct dlm_ctxt *dlm = dlm_ctxt_from_user_lockres(lockres); 4148df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 4158df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh if (level != LKM_EXMODE && 4168df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh level != LKM_PRMODE) { 417ea5b3a187e2724fa9d08b2fbd3898c149ed95c6bMark Fasheh mlog(ML_ERROR, "lockres %.*s: invalid request!\n", 418ea5b3a187e2724fa9d08b2fbd3898c149ed95c6bMark Fasheh lockres->l_namelen, lockres->l_name); 4198df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh status = -EINVAL; 4208df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh goto bail; 4218df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh } 4228df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 423ea5b3a187e2724fa9d08b2fbd3898c149ed95c6bMark Fasheh mlog(0, "lockres %.*s: asking for %s lock, passed flags = 0x%x\n", 424ea5b3a187e2724fa9d08b2fbd3898c149ed95c6bMark Fasheh lockres->l_namelen, lockres->l_name, 425ea5b3a187e2724fa9d08b2fbd3898c149ed95c6bMark Fasheh (level == LKM_EXMODE) ? "LKM_EXMODE" : "LKM_PRMODE", 426ea5b3a187e2724fa9d08b2fbd3898c149ed95c6bMark Fasheh lkm_flags); 4278df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 4288df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fashehagain: 4298df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh if (signal_pending(current)) { 4308df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh status = -ERESTARTSYS; 4318df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh goto bail; 4328df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh } 4338df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 4348df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh spin_lock(&lockres->l_lock); 4358df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 4368df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh /* We only compare against the currently granted level 4378df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh * here. If the lock is blocked waiting on a downconvert, 4388df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh * we'll get caught below. */ 4398df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh if ((lockres->l_flags & USER_LOCK_BUSY) && 4408df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh (level > lockres->l_level)) { 4418df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh /* is someone sitting in dlm_lock? If so, wait on 4428df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh * them. */ 4438df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh spin_unlock(&lockres->l_lock); 4448df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 4458df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh user_wait_on_busy_lock(lockres); 4468df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh goto again; 4478df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh } 4488df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 4498df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh if ((lockres->l_flags & USER_LOCK_BLOCKED) && 4508df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh (!user_may_continue_on_blocked_lock(lockres, level))) { 4518df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh /* is the lock is currently blocked on behalf of 4528df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh * another node */ 4538df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh spin_unlock(&lockres->l_lock); 4548df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 4558df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh user_wait_on_blocked_lock(lockres); 4568df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh goto again; 4578df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh } 4588df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 4598df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh if (level > lockres->l_level) { 4608df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh local_flags = lkm_flags | LKM_VALBLK; 4618df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh if (lockres->l_level != LKM_IVMODE) 4628df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh local_flags |= LKM_CONVERT; 4638df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 4648df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh lockres->l_requested = level; 4658df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh lockres->l_flags |= USER_LOCK_BUSY; 4668df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh spin_unlock(&lockres->l_lock); 4678df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 4688df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh BUG_ON(level == LKM_IVMODE); 4698df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh BUG_ON(level == LKM_NLMODE); 4708df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 4718df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh /* call dlm_lock to upgrade lock now */ 4728df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh status = dlmlock(dlm, 4738df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh level, 4748df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh &lockres->l_lksb, 4758df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh local_flags, 4768df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh lockres->l_name, 477ea5b3a187e2724fa9d08b2fbd3898c149ed95c6bMark Fasheh lockres->l_namelen, 4788df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh user_ast, 4798df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh lockres, 4808df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh user_bast); 4818df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh if (status != DLM_NORMAL) { 4828df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh if ((lkm_flags & LKM_NOQUEUE) && 4838df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh (status == DLM_NOTQUEUED)) 4848df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh status = -EAGAIN; 4858df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh else { 4868df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh user_log_dlm_error("dlmlock", status, lockres); 4878df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh status = -EINVAL; 4888df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh } 4898df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh user_recover_from_dlm_error(lockres); 4908df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh goto bail; 4918df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh } 4928df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 4938df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh user_wait_on_busy_lock(lockres); 4948df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh goto again; 4958df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh } 4968df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 4978df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh user_dlm_inc_holders(lockres, level); 4988df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh spin_unlock(&lockres->l_lock); 4998df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 5008df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh status = 0; 5018df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fashehbail: 5028df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh return status; 5038df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh} 5048df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 5058df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fashehstatic inline void user_dlm_dec_holders(struct user_lock_res *lockres, 5068df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh int level) 5078df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh{ 5088df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh switch(level) { 5098df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh case LKM_EXMODE: 5108df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh BUG_ON(!lockres->l_ex_holders); 5118df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh lockres->l_ex_holders--; 5128df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh break; 5138df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh case LKM_PRMODE: 5148df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh BUG_ON(!lockres->l_ro_holders); 5158df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh lockres->l_ro_holders--; 5168df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh break; 5178df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh default: 5188df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh BUG(); 5198df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh } 5208df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh} 5218df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 5228df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fashehvoid user_dlm_cluster_unlock(struct user_lock_res *lockres, 5238df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh int level) 5248df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh{ 5258df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh if (level != LKM_EXMODE && 5268df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh level != LKM_PRMODE) { 527ea5b3a187e2724fa9d08b2fbd3898c149ed95c6bMark Fasheh mlog(ML_ERROR, "lockres %.*s: invalid request!\n", 528ea5b3a187e2724fa9d08b2fbd3898c149ed95c6bMark Fasheh lockres->l_namelen, lockres->l_name); 5298df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh return; 5308df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh } 5318df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 5328df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh spin_lock(&lockres->l_lock); 5338df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh user_dlm_dec_holders(lockres, level); 5348df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh __user_dlm_cond_queue_lockres(lockres); 5358df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh spin_unlock(&lockres->l_lock); 5368df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh} 5378df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 5388df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fashehvoid user_dlm_write_lvb(struct inode *inode, 5398df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh const char *val, 5408df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh unsigned int len) 5418df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh{ 5428df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh struct user_lock_res *lockres = &DLMFS_I(inode)->ip_lockres; 5438df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh char *lvb = lockres->l_lksb.lvb; 5448df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 5458df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh BUG_ON(len > DLM_LVB_LEN); 5468df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 5478df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh spin_lock(&lockres->l_lock); 5488df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 5498df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh BUG_ON(lockres->l_level < LKM_EXMODE); 5508df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh memcpy(lvb, val, len); 5518df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 5528df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh spin_unlock(&lockres->l_lock); 5538df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh} 5548df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 5558df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fashehvoid user_dlm_read_lvb(struct inode *inode, 5568df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh char *val, 5578df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh unsigned int len) 5588df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh{ 5598df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh struct user_lock_res *lockres = &DLMFS_I(inode)->ip_lockres; 5608df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh char *lvb = lockres->l_lksb.lvb; 5618df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 5628df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh BUG_ON(len > DLM_LVB_LEN); 5638df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 5648df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh spin_lock(&lockres->l_lock); 5658df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 5668df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh BUG_ON(lockres->l_level < LKM_PRMODE); 5678df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh memcpy(val, lvb, len); 5688df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 5698df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh spin_unlock(&lockres->l_lock); 5708df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh} 5718df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 5728df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fashehvoid user_dlm_lock_res_init(struct user_lock_res *lockres, 5738df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh struct dentry *dentry) 5748df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh{ 5758df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh memset(lockres, 0, sizeof(*lockres)); 5768df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 5778df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh spin_lock_init(&lockres->l_lock); 5788df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh init_waitqueue_head(&lockres->l_event); 5798df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh lockres->l_level = LKM_IVMODE; 5808df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh lockres->l_requested = LKM_IVMODE; 5818df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh lockres->l_blocking = LKM_IVMODE; 5828df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 5838df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh /* should have been checked before getting here. */ 5848df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh BUG_ON(dentry->d_name.len >= USER_DLM_LOCK_ID_MAX_LEN); 5858df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 5868df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh memcpy(lockres->l_name, 5878df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh dentry->d_name.name, 5888df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh dentry->d_name.len); 589ea5b3a187e2724fa9d08b2fbd3898c149ed95c6bMark Fasheh lockres->l_namelen = dentry->d_name.len; 5908df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh} 5918df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 5928df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fashehint user_dlm_destroy_lock(struct user_lock_res *lockres) 5938df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh{ 5948df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh int status = -EBUSY; 5958df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh struct dlm_ctxt *dlm = dlm_ctxt_from_user_lockres(lockres); 5968df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 597ea5b3a187e2724fa9d08b2fbd3898c149ed95c6bMark Fasheh mlog(0, "asked to destroy %.*s\n", lockres->l_namelen, lockres->l_name); 5988df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 5998df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh spin_lock(&lockres->l_lock); 6002cd9888590c52ac7592e3607d0a3174ccd57ef86Mark Fasheh if (lockres->l_flags & USER_LOCK_IN_TEARDOWN) { 6012cd9888590c52ac7592e3607d0a3174ccd57ef86Mark Fasheh spin_unlock(&lockres->l_lock); 6022cd9888590c52ac7592e3607d0a3174ccd57ef86Mark Fasheh return 0; 6032cd9888590c52ac7592e3607d0a3174ccd57ef86Mark Fasheh } 6042cd9888590c52ac7592e3607d0a3174ccd57ef86Mark Fasheh 6052cd9888590c52ac7592e3607d0a3174ccd57ef86Mark Fasheh lockres->l_flags |= USER_LOCK_IN_TEARDOWN; 6062cd9888590c52ac7592e3607d0a3174ccd57ef86Mark Fasheh 6078df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh while (lockres->l_flags & USER_LOCK_BUSY) { 6088df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh spin_unlock(&lockres->l_lock); 6098df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 6108df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh user_wait_on_busy_lock(lockres); 6118df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 6128df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh spin_lock(&lockres->l_lock); 6138df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh } 6148df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 6158df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh if (lockres->l_ro_holders || lockres->l_ex_holders) { 6168df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh spin_unlock(&lockres->l_lock); 6178df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh goto bail; 6188df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh } 6198df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 6208df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh status = 0; 6218df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh if (!(lockres->l_flags & USER_LOCK_ATTACHED)) { 6228df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh spin_unlock(&lockres->l_lock); 6238df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh goto bail; 6248df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh } 6258df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 6268df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh lockres->l_flags &= ~USER_LOCK_ATTACHED; 6278df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh lockres->l_flags |= USER_LOCK_BUSY; 6288df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh spin_unlock(&lockres->l_lock); 6298df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 6308df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh status = dlmunlock(dlm, 6318df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh &lockres->l_lksb, 6328df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh LKM_VALBLK, 6338df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh user_unlock_ast, 6348df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh lockres); 6358df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh if (status != DLM_NORMAL) { 6368df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh user_log_dlm_error("dlmunlock", status, lockres); 6378df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh status = -EINVAL; 6388df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh goto bail; 6398df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh } 6408df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 6418df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh user_wait_on_busy_lock(lockres); 6428df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 6438df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh status = 0; 6448df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fashehbail: 6458df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh return status; 6468df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh} 6478df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 6488df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fashehstruct dlm_ctxt *user_dlm_register_context(struct qstr *name) 6498df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh{ 6508df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh struct dlm_ctxt *dlm; 6518df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh u32 dlm_key; 6528df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh char *domain; 6538df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 654ad8100e0d20e0123def9f83c040b68c96c8638f0Kurt Hackel domain = kmalloc(name->len + 1, GFP_NOFS); 6558df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh if (!domain) { 6568df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh mlog_errno(-ENOMEM); 6578df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh return ERR_PTR(-ENOMEM); 6588df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh } 6598df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 6608df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh dlm_key = crc32_le(0, name->name, name->len); 6618df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 6628df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh snprintf(domain, name->len + 1, "%.*s", name->len, name->name); 6638df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 6648df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh dlm = dlm_register_domain(domain, dlm_key); 6658df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh if (IS_ERR(dlm)) 6668df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh mlog_errno(PTR_ERR(dlm)); 6678df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 6688df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh kfree(domain); 6698df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh return dlm; 6708df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh} 6718df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh 6728df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fashehvoid user_dlm_unregister_context(struct dlm_ctxt *dlm) 6738df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh{ 6748df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh dlm_unregister_domain(dlm); 6758df08c89c668e1bd922a053fdb5ba1fadbecbb38Mark Fasheh} 676