⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dlmglue.c

📁 ocfs1.4.1 oracle分布式文件系统
💻 C
📖 第 1 页 / 共 5 页
字号:
				       struct ocfs2_lock_res *res,				       enum ocfs2_lock_type type,				       struct ocfs2_lock_res_ops *ops,				       void *priv){	res->l_type          = type;	res->l_ops           = ops;	res->l_priv          = priv;	res->l_level         = LKM_IVMODE;	res->l_requested     = LKM_IVMODE;	res->l_blocking      = LKM_IVMODE;	res->l_action        = OCFS2_AST_INVALID;	res->l_unlock_action = OCFS2_UNLOCK_INVALID;	res->l_flags         = OCFS2_LOCK_INITIALIZED;	ocfs2_add_lockres_tracking(res, osb->osb_dlm_debug);	ocfs2_init_lock_stats(res);}void ocfs2_lock_res_init_once(struct ocfs2_lock_res *res){	/* This also clears out the lock status block */	memset(res, 0, sizeof(struct ocfs2_lock_res));	spin_lock_init(&res->l_lock);	init_waitqueue_head(&res->l_event);	INIT_LIST_HEAD(&res->l_blocked_list);	INIT_LIST_HEAD(&res->l_mask_waiters);}void ocfs2_inode_lock_res_init(struct ocfs2_lock_res *res,			       enum ocfs2_lock_type type,			       unsigned int generation,			       struct inode *inode){	struct ocfs2_lock_res_ops *ops;	switch(type) {		case OCFS2_LOCK_TYPE_RW:			ops = &ocfs2_inode_rw_lops;			break;		case OCFS2_LOCK_TYPE_META:			ops = &ocfs2_inode_inode_lops;			break;		case OCFS2_LOCK_TYPE_OPEN:			ops = &ocfs2_inode_open_lops;			break;		default:			mlog_bug_on_msg(1, "type: %d\n", type);			ops = NULL; /* thanks, gcc */			break;	};	ocfs2_build_lock_name(type, OCFS2_I(inode)->ip_blkno,			      generation, res->l_name);	ocfs2_lock_res_init_common(OCFS2_SB(inode->i_sb), res, type, ops, inode);}static struct ocfs2_super *ocfs2_get_inode_osb(struct ocfs2_lock_res *lockres){	struct inode *inode = ocfs2_lock_res_inode(lockres);	return OCFS2_SB(inode->i_sb);}static struct ocfs2_super *ocfs2_get_file_osb(struct ocfs2_lock_res *lockres){	struct ocfs2_file_private *fp = lockres->l_priv;	return OCFS2_SB(fp->fp_file->f_mapping->host->i_sb);}static __u64 ocfs2_get_dentry_lock_ino(struct ocfs2_lock_res *lockres){	__be64 inode_blkno_be;	memcpy(&inode_blkno_be, &lockres->l_name[OCFS2_DENTRY_LOCK_INO_START],	       sizeof(__be64));	return be64_to_cpu(inode_blkno_be);}static struct ocfs2_super *ocfs2_get_dentry_osb(struct ocfs2_lock_res *lockres){	struct ocfs2_dentry_lock *dl = lockres->l_priv;	return OCFS2_SB(dl->dl_inode->i_sb);}void ocfs2_dentry_lock_res_init(struct ocfs2_dentry_lock *dl,				u64 parent, struct inode *inode){	int len;	u64 inode_blkno = OCFS2_I(inode)->ip_blkno;	__be64 inode_blkno_be = cpu_to_be64(inode_blkno);	struct ocfs2_lock_res *lockres = &dl->dl_lockres;	ocfs2_lock_res_init_once(lockres);	/*	 * Unfortunately, the standard lock naming scheme won't work	 * here because we have two 16 byte values to use. Instead,	 * we'll stuff the inode number as a binary value. We still	 * want error prints to show something without garbling the	 * display, so drop a null byte in there before the inode	 * number. A future version of OCFS2 will likely use all	 * binary lock names. The stringified names have been a	 * tremendous aid in debugging, but now that the debugfs	 * interface exists, we can mangle things there if need be.	 *	 * NOTE: We also drop the standard "pad" value (the total lock	 * name size stays the same though - the last part is all	 * zeros due to the memset in ocfs2_lock_res_init_once()	 */	len = snprintf(lockres->l_name, OCFS2_DENTRY_LOCK_INO_START,		       "%c%016llx",		       ocfs2_lock_type_char(OCFS2_LOCK_TYPE_DENTRY),		       (long long)parent);	BUG_ON(len != (OCFS2_DENTRY_LOCK_INO_START - 1));	memcpy(&lockres->l_name[OCFS2_DENTRY_LOCK_INO_START], &inode_blkno_be,	       sizeof(__be64));	ocfs2_lock_res_init_common(OCFS2_SB(inode->i_sb), lockres,				   OCFS2_LOCK_TYPE_DENTRY, &ocfs2_dentry_lops,				   dl);}static void ocfs2_super_lock_res_init(struct ocfs2_lock_res *res,				      struct ocfs2_super *osb){	/* Superblock lockres doesn't come from a slab so we call init	 * once on it manually.  */	ocfs2_lock_res_init_once(res);	ocfs2_build_lock_name(OCFS2_LOCK_TYPE_SUPER, OCFS2_SUPER_BLOCK_BLKNO,			      0, res->l_name);	ocfs2_lock_res_init_common(osb, res, OCFS2_LOCK_TYPE_SUPER,				   &ocfs2_super_lops, osb);}static void ocfs2_rename_lock_res_init(struct ocfs2_lock_res *res,				       struct ocfs2_super *osb){	/* Rename lockres doesn't come from a slab so we call init	 * once on it manually.  */	ocfs2_lock_res_init_once(res);	ocfs2_build_lock_name(OCFS2_LOCK_TYPE_RENAME, 0, 0, res->l_name);	ocfs2_lock_res_init_common(osb, res, OCFS2_LOCK_TYPE_RENAME,				   &ocfs2_rename_lops, osb);}void ocfs2_file_lock_res_init(struct ocfs2_lock_res *lockres,			      struct ocfs2_file_private *fp){	struct inode *inode = fp->fp_file->f_mapping->host;	struct ocfs2_inode_info *oi = OCFS2_I(inode);	ocfs2_lock_res_init_once(lockres);	ocfs2_build_lock_name(OCFS2_LOCK_TYPE_FLOCK, oi->ip_blkno,			      inode->i_generation, lockres->l_name);	ocfs2_lock_res_init_common(OCFS2_SB(inode->i_sb), lockres,				   OCFS2_LOCK_TYPE_FLOCK, &ocfs2_flock_lops,				   fp);	lockres->l_flags |= OCFS2_LOCK_NOCACHE;}void ocfs2_lock_res_free(struct ocfs2_lock_res *res){	mlog_entry_void();	if (!(res->l_flags & OCFS2_LOCK_INITIALIZED))		return;	ocfs2_remove_lockres_tracking(res);	mlog_bug_on_msg(!list_empty(&res->l_blocked_list),			"Lockres %s is on the blocked list\n",			res->l_name);	mlog_bug_on_msg(!list_empty(&res->l_mask_waiters),			"Lockres %s has mask waiters pending\n",			res->l_name);	mlog_bug_on_msg(spin_is_locked(&res->l_lock),			"Lockres %s is locked\n",			res->l_name);	mlog_bug_on_msg(res->l_ro_holders,			"Lockres %s has %u ro holders\n",			res->l_name, res->l_ro_holders);	mlog_bug_on_msg(res->l_ex_holders,			"Lockres %s has %u ex holders\n",			res->l_name, res->l_ex_holders);	/* Need to clear out the lock status block for the dlm */	memset(&res->l_lksb, 0, sizeof(res->l_lksb));	res->l_flags = 0UL;	mlog_exit_void();}static inline void ocfs2_inc_holders(struct ocfs2_lock_res *lockres,				     int level){	mlog_entry_void();	BUG_ON(!lockres);	switch(level) {	case LKM_EXMODE:		lockres->l_ex_holders++;		break;	case LKM_PRMODE:		lockres->l_ro_holders++;		break;	default:		BUG();	}	mlog_exit_void();}static inline void ocfs2_dec_holders(struct ocfs2_lock_res *lockres,				     int level){	mlog_entry_void();	BUG_ON(!lockres);	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();	}	mlog_exit_void();}/* WARNING: This function lives in a world where the only three lock * levels are EX, PR, and NL. It *will* have to be adjusted when more * lock types are added. */static inline int ocfs2_highest_compat_lock_level(int level){	int new_level = LKM_EXMODE;	if (level == LKM_EXMODE)		new_level = LKM_NLMODE;	else if (level == LKM_PRMODE)		new_level = LKM_PRMODE;	return new_level;}static void lockres_set_flags(struct ocfs2_lock_res *lockres,			      unsigned long newflags){	struct ocfs2_mask_waiter *mw, *tmp; 	assert_spin_locked(&lockres->l_lock);	lockres->l_flags = newflags;	list_for_each_entry_safe(mw, tmp, &lockres->l_mask_waiters, mw_item) {		if ((lockres->l_flags & mw->mw_mask) != mw->mw_goal)			continue;		list_del_init(&mw->mw_item);		mw->mw_status = 0;		complete(&mw->mw_complete);	}}static void lockres_or_flags(struct ocfs2_lock_res *lockres, unsigned long or){	lockres_set_flags(lockres, lockres->l_flags | or);}static void lockres_clear_flags(struct ocfs2_lock_res *lockres,				unsigned long clear){	lockres_set_flags(lockres, lockres->l_flags & ~clear);}static inline void ocfs2_generic_handle_downconvert_action(struct ocfs2_lock_res *lockres){	mlog_entry_void();	BUG_ON(!(lockres->l_flags & OCFS2_LOCK_BUSY));	BUG_ON(!(lockres->l_flags & OCFS2_LOCK_ATTACHED));	BUG_ON(!(lockres->l_flags & OCFS2_LOCK_BLOCKED));	BUG_ON(lockres->l_blocking <= LKM_NLMODE);	lockres->l_level = lockres->l_requested;	if (lockres->l_level <=	    ocfs2_highest_compat_lock_level(lockres->l_blocking)) {		lockres->l_blocking = LKM_NLMODE;		lockres_clear_flags(lockres, OCFS2_LOCK_BLOCKED);	}	lockres_clear_flags(lockres, OCFS2_LOCK_BUSY);	mlog_exit_void();}static inline void ocfs2_generic_handle_convert_action(struct ocfs2_lock_res *lockres){	mlog_entry_void();	BUG_ON(!(lockres->l_flags & OCFS2_LOCK_BUSY));	BUG_ON(!(lockres->l_flags & OCFS2_LOCK_ATTACHED));	/* Convert from RO to EX doesn't really need anything as our	 * information is already up to data. Convert from NL to	 * *anything* however should mark ourselves as needing an	 * update */	if (lockres->l_level == LKM_NLMODE &&	    lockres->l_ops->flags & LOCK_TYPE_REQUIRES_REFRESH)		lockres_or_flags(lockres, OCFS2_LOCK_NEEDS_REFRESH);	lockres->l_level = lockres->l_requested;	lockres_clear_flags(lockres, OCFS2_LOCK_BUSY);	mlog_exit_void();}static inline void ocfs2_generic_handle_attach_action(struct ocfs2_lock_res *lockres){	mlog_entry_void();	BUG_ON((!(lockres->l_flags & OCFS2_LOCK_BUSY)));	BUG_ON(lockres->l_flags & OCFS2_LOCK_ATTACHED);	if (lockres->l_requested > LKM_NLMODE &&	    !(lockres->l_flags & OCFS2_LOCK_LOCAL) &&	    lockres->l_ops->flags & LOCK_TYPE_REQUIRES_REFRESH)		lockres_or_flags(lockres, OCFS2_LOCK_NEEDS_REFRESH);	lockres->l_level = lockres->l_requested;	lockres_or_flags(lockres, OCFS2_LOCK_ATTACHED);	lockres_clear_flags(lockres, OCFS2_LOCK_BUSY);	mlog_exit_void();}static int ocfs2_generic_handle_bast(struct ocfs2_lock_res *lockres,				     int level){	int needs_downconvert = 0;	mlog_entry_void();	assert_spin_locked(&lockres->l_lock);	lockres_or_flags(lockres, OCFS2_LOCK_BLOCKED);	if (level > lockres->l_blocking) {		/* only schedule a downconvert if we haven't already scheduled		 * one that goes low enough to satisfy the level we're		 * blocking.  this also catches the case where we get		 * duplicate BASTs */		if (ocfs2_highest_compat_lock_level(level) <		    ocfs2_highest_compat_lock_level(lockres->l_blocking))			needs_downconvert = 1;		lockres->l_blocking = level;	}	mlog_exit(needs_downconvert);	return needs_downconvert;}static void ocfs2_blocking_ast(void *opaque, int level){	struct ocfs2_lock_res *lockres = opaque;	struct ocfs2_super *osb = ocfs2_get_lockres_osb(lockres);	int needs_downconvert;	unsigned long flags;	BUG_ON(level <= LKM_NLMODE);	mlog(0, "BAST fired for lockres %s, blocking %d, level %d type %s\n",	     lockres->l_name, level, lockres->l_level,	     ocfs2_lock_type_string(lockres->l_type));	/*	 * We can skip the bast for locks which don't enable caching -	 * they'll be dropped at the earliest possible time anyway.	 */	if (lockres->l_flags & OCFS2_LOCK_NOCACHE)		return;	spin_lock_irqsave(&lockres->l_lock, flags);	needs_downconvert = ocfs2_generic_handle_bast(lockres, level);	if (needs_downconvert)		ocfs2_schedule_blocked_lock(osb, lockres);	spin_unlock_irqrestore(&lockres->l_lock, flags);	wake_up(&lockres->l_event);	ocfs2_wake_downconvert_thread(osb);}static void ocfs2_locking_ast(void *opaque){	struct ocfs2_lock_res *lockres = opaque;	struct dlm_lockstatus *lksb = &lockres->l_lksb;	unsigned long flags;	spin_lock_irqsave(&lockres->l_lock, flags);	if (lksb->status != DLM_NORMAL) {		mlog(ML_ERROR, "lockres %s: lksb status value of %u!\n",		     lockres->l_name, lksb->status);		spin_unlock_irqrestore(&lockres->l_lock, flags);		return;	}	switch(lockres->l_action) {	case OCFS2_AST_ATTACH:		ocfs2_generic_handle_attach_action(lockres);		lockres_clear_flags(lockres, OCFS2_LOCK_LOCAL);		break;	case OCFS2_AST_CONVERT:		ocfs2_generic_handle_convert_action(lockres);		break;	case OCFS2_AST_DOWNCONVERT:		ocfs2_generic_handle_downconvert_action(lockres);		break;	default:		mlog(ML_ERROR, "lockres %s: ast fired with invalid action: %u "		     "lockres flags = 0x%lx, unlock action: %u\n",		     lockres->l_name, lockres->l_action, lockres->l_flags,		     lockres->l_unlock_action);		BUG();	}	/* set it to something invalid so if we get called again we	 * can catch it. */	lockres->l_action = OCFS2_AST_INVALID;	wake_up(&lockres->l_event);	spin_unlock_irqrestore(&lockres->l_lock, flags);}static inline void ocfs2_recover_from_dlm_error(struct ocfs2_lock_res *lockres,						int convert){	unsigned long flags;	mlog_entry_void();	spin_lock_irqsave(&lockres->l_lock, flags);	lockres_clear_flags(lockres, OCFS2_LOCK_BUSY);	if (convert)		lockres->l_action = OCFS2_AST_INVALID;	else		lockres->l_unlock_action = OCFS2_UNLOCK_INVALID;	spin_unlock_irqrestore(&lockres->l_lock, flags);	wake_up(&lockres->l_event);	mlog_exit_void();}/* Note: If we detect another process working on the lock (i.e., * OCFS2_LOCK_BUSY), we'll bail out returning 0. It's up to the caller * to do the right thing in that case. */static int ocfs2_lock_create(struct ocfs2_super *osb,			     struct ocfs2_lock_res *lockres,			     int level,			     int dlm_flags){

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -