📄 userdlm.c
字号:
spin_unlock(&lockres->l_lock); mlog(0, "can't downconvert for ex: ro = %u, ex = %u\n", lockres->l_ro_holders, lockres->l_ex_holders); goto drop_ref; } if ((lockres->l_blocking == LKM_PRMODE) && lockres->l_ex_holders) { spin_unlock(&lockres->l_lock); mlog(0, "can't downconvert for pr: ex = %u\n", lockres->l_ex_holders); goto drop_ref; } /* yay, we can downconvert now. */ new_level = user_highest_compat_lock_level(lockres->l_blocking); lockres->l_requested = new_level; lockres->l_flags |= USER_LOCK_BUSY; mlog(0, "Downconvert lock from %d to %d\n", lockres->l_level, new_level); spin_unlock(&lockres->l_lock); /* need lock downconvert request now... */ status = dlmlock(dlm, new_level, &lockres->l_lksb, LKM_CONVERT|LKM_VALBLK, lockres->l_name, lockres->l_namelen, user_ast, lockres, user_bast); if (status != DLM_NORMAL) { user_log_dlm_error("dlmlock", status, lockres); user_recover_from_dlm_error(lockres); }drop_ref: user_dlm_drop_inode_ref(lockres);}static inline void user_dlm_inc_holders(struct user_lock_res *lockres, int level){ switch(level) { case LKM_EXMODE: lockres->l_ex_holders++; break; case LKM_PRMODE: lockres->l_ro_holders++; break; default: BUG(); }}/* predict what lock level we'll be dropping down to on behalf * of another node, and return true if the currently wanted * level will be compatible with it. */static inline intuser_may_continue_on_blocked_lock(struct user_lock_res *lockres, int wanted){ BUG_ON(!(lockres->l_flags & USER_LOCK_BLOCKED)); return wanted <= user_highest_compat_lock_level(lockres->l_blocking);}int user_dlm_cluster_lock(struct user_lock_res *lockres, int level, int lkm_flags){ int status, local_flags; struct dlm_ctxt *dlm = dlm_ctxt_from_user_lockres(lockres); if (level != LKM_EXMODE && level != LKM_PRMODE) { mlog(ML_ERROR, "lockres %.*s: invalid request!\n", lockres->l_namelen, lockres->l_name); status = -EINVAL; goto bail; } mlog(0, "lockres %.*s: asking for %s lock, passed flags = 0x%x\n", lockres->l_namelen, lockres->l_name, (level == LKM_EXMODE) ? "LKM_EXMODE" : "LKM_PRMODE", lkm_flags);again: if (signal_pending(current)) { status = -ERESTARTSYS; goto bail; } spin_lock(&lockres->l_lock); /* We only compare against the currently granted level * here. If the lock is blocked waiting on a downconvert, * we'll get caught below. */ if ((lockres->l_flags & USER_LOCK_BUSY) && (level > lockres->l_level)) { /* is someone sitting in dlm_lock? If so, wait on * them. */ spin_unlock(&lockres->l_lock); user_wait_on_busy_lock(lockres); goto again; } if ((lockres->l_flags & USER_LOCK_BLOCKED) && (!user_may_continue_on_blocked_lock(lockres, level))) { /* is the lock is currently blocked on behalf of * another node */ spin_unlock(&lockres->l_lock); user_wait_on_blocked_lock(lockres); goto again; } if (level > lockres->l_level) { local_flags = lkm_flags | LKM_VALBLK; if (lockres->l_level != LKM_IVMODE) local_flags |= LKM_CONVERT; lockres->l_requested = level; lockres->l_flags |= USER_LOCK_BUSY; spin_unlock(&lockres->l_lock); BUG_ON(level == LKM_IVMODE); BUG_ON(level == LKM_NLMODE); /* call dlm_lock to upgrade lock now */ status = dlmlock(dlm, level, &lockres->l_lksb, local_flags, lockres->l_name, lockres->l_namelen, user_ast, lockres, user_bast); if (status != DLM_NORMAL) { if ((lkm_flags & LKM_NOQUEUE) && (status == DLM_NOTQUEUED)) status = -EAGAIN; else { user_log_dlm_error("dlmlock", status, lockres); status = -EINVAL; } user_recover_from_dlm_error(lockres); goto bail; } user_wait_on_busy_lock(lockres); goto again; } user_dlm_inc_holders(lockres, level); spin_unlock(&lockres->l_lock); status = 0;bail: return status;}static inline void user_dlm_dec_holders(struct user_lock_res *lockres, int level){ switch(level) { case LKM_EXMODE: BUG_ON(!lockres->l_ex_holders); lockres->l_ex_holders--; break; case LKM_PRMODE: BUG_ON(!lockres->l_ro_holders); lockres->l_ro_holders--; break; default: BUG(); }}void user_dlm_cluster_unlock(struct user_lock_res *lockres, int level){ if (level != LKM_EXMODE && level != LKM_PRMODE) { mlog(ML_ERROR, "lockres %.*s: invalid request!\n", lockres->l_namelen, lockres->l_name); return; } spin_lock(&lockres->l_lock); user_dlm_dec_holders(lockres, level); __user_dlm_cond_queue_lockres(lockres); spin_unlock(&lockres->l_lock);}void user_dlm_write_lvb(struct inode *inode, const char *val, unsigned int len){ struct user_lock_res *lockres = &DLMFS_I(inode)->ip_lockres; char *lvb = lockres->l_lksb.lvb; BUG_ON(len > DLM_LVB_LEN); spin_lock(&lockres->l_lock); BUG_ON(lockres->l_level < LKM_EXMODE); memcpy(lvb, val, len); spin_unlock(&lockres->l_lock);}void user_dlm_read_lvb(struct inode *inode, char *val, unsigned int len){ struct user_lock_res *lockres = &DLMFS_I(inode)->ip_lockres; char *lvb = lockres->l_lksb.lvb; BUG_ON(len > DLM_LVB_LEN); spin_lock(&lockres->l_lock); BUG_ON(lockres->l_level < LKM_PRMODE); memcpy(val, lvb, len); spin_unlock(&lockres->l_lock);}void user_dlm_lock_res_init(struct user_lock_res *lockres, struct dentry *dentry){ memset(lockres, 0, sizeof(*lockres)); spin_lock_init(&lockres->l_lock); init_waitqueue_head(&lockres->l_event); lockres->l_level = LKM_IVMODE; lockres->l_requested = LKM_IVMODE; lockres->l_blocking = LKM_IVMODE; /* should have been checked before getting here. */ BUG_ON(dentry->d_name.len >= USER_DLM_LOCK_ID_MAX_LEN); memcpy(lockres->l_name, dentry->d_name.name, dentry->d_name.len); lockres->l_namelen = dentry->d_name.len;}int user_dlm_destroy_lock(struct user_lock_res *lockres){ int status = -EBUSY; struct dlm_ctxt *dlm = dlm_ctxt_from_user_lockres(lockres); mlog(0, "asked to destroy %.*s\n", lockres->l_namelen, lockres->l_name); spin_lock(&lockres->l_lock); if (lockres->l_flags & USER_LOCK_IN_TEARDOWN) { spin_unlock(&lockres->l_lock); return 0; } lockres->l_flags |= USER_LOCK_IN_TEARDOWN; while (lockres->l_flags & USER_LOCK_BUSY) { spin_unlock(&lockres->l_lock); user_wait_on_busy_lock(lockres); spin_lock(&lockres->l_lock); } if (lockres->l_ro_holders || lockres->l_ex_holders) { spin_unlock(&lockres->l_lock); goto bail; } status = 0; if (!(lockres->l_flags & USER_LOCK_ATTACHED)) { spin_unlock(&lockres->l_lock); goto bail; } lockres->l_flags &= ~USER_LOCK_ATTACHED; lockres->l_flags |= USER_LOCK_BUSY; spin_unlock(&lockres->l_lock); status = dlmunlock(dlm, &lockres->l_lksb, LKM_VALBLK, user_unlock_ast, lockres); if (status != DLM_NORMAL) { user_log_dlm_error("dlmunlock", status, lockres); status = -EINVAL; goto bail; } user_wait_on_busy_lock(lockres); status = 0;bail: return status;}struct dlm_ctxt *user_dlm_register_context(struct qstr *name, struct dlm_protocol_version *proto){ struct dlm_ctxt *dlm; u32 dlm_key; char *domain; domain = kmalloc(name->len + 1, GFP_NOFS); if (!domain) { mlog_errno(-ENOMEM); return ERR_PTR(-ENOMEM); } dlm_key = crc32_le(0, name->name, name->len); snprintf(domain, name->len + 1, "%.*s", name->len, name->name); dlm = dlm_register_domain(domain, dlm_key, proto); if (IS_ERR(dlm)) mlog_errno(PTR_ERR(dlm)); kfree(domain); return dlm;}void user_dlm_unregister_context(struct dlm_ctxt *dlm){ dlm_unregister_domain(dlm);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -