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

📄 dlmglue.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
		status = ocfs2_read_block(osb, bh->b_blocknr, &bh, 0,					  si->si_inode);		if (status == 0)			ocfs2_update_slot_info(si);		ocfs2_complete_lock_res_refresh(lockres, status);		if (status < 0)			mlog_errno(status);	}bail:	mlog_exit(status);	return status;}void ocfs2_super_unlock(struct ocfs2_super *osb,			int ex){	int level = ex ? LKM_EXMODE : LKM_PRMODE;	struct ocfs2_lock_res *lockres = &osb->osb_super_lockres;	if (!ocfs2_mount_local(osb))		ocfs2_cluster_unlock(osb, lockres, level);}int ocfs2_rename_lock(struct ocfs2_super *osb){	int status;	struct ocfs2_lock_res *lockres = &osb->osb_rename_lockres;	if (ocfs2_is_hard_readonly(osb))		return -EROFS;	if (ocfs2_mount_local(osb))		return 0;	status = ocfs2_cluster_lock(osb, lockres, LKM_EXMODE, 0, 0);	if (status < 0)		mlog_errno(status);	return status;}void ocfs2_rename_unlock(struct ocfs2_super *osb){	struct ocfs2_lock_res *lockres = &osb->osb_rename_lockres;	if (!ocfs2_mount_local(osb))		ocfs2_cluster_unlock(osb, lockres, LKM_EXMODE);}int ocfs2_dentry_lock(struct dentry *dentry, int ex){	int ret;	int level = ex ? LKM_EXMODE : LKM_PRMODE;	struct ocfs2_dentry_lock *dl = dentry->d_fsdata;	struct ocfs2_super *osb = OCFS2_SB(dentry->d_sb);	BUG_ON(!dl);	if (ocfs2_is_hard_readonly(osb))		return -EROFS;	if (ocfs2_mount_local(osb))		return 0;	ret = ocfs2_cluster_lock(osb, &dl->dl_lockres, level, 0, 0);	if (ret < 0)		mlog_errno(ret);	return ret;}void ocfs2_dentry_unlock(struct dentry *dentry, int ex){	int level = ex ? LKM_EXMODE : LKM_PRMODE;	struct ocfs2_dentry_lock *dl = dentry->d_fsdata;	struct ocfs2_super *osb = OCFS2_SB(dentry->d_sb);	if (!ocfs2_mount_local(osb))		ocfs2_cluster_unlock(osb, &dl->dl_lockres, level);}/* Reference counting of the dlm debug structure. We want this because * open references on the debug inodes can live on after a mount, so * we can't rely on the ocfs2_super to always exist. */static void ocfs2_dlm_debug_free(struct kref *kref){	struct ocfs2_dlm_debug *dlm_debug;	dlm_debug = container_of(kref, struct ocfs2_dlm_debug, d_refcnt);	kfree(dlm_debug);}void ocfs2_put_dlm_debug(struct ocfs2_dlm_debug *dlm_debug){	if (dlm_debug)		kref_put(&dlm_debug->d_refcnt, ocfs2_dlm_debug_free);}static void ocfs2_get_dlm_debug(struct ocfs2_dlm_debug *debug){	kref_get(&debug->d_refcnt);}struct ocfs2_dlm_debug *ocfs2_new_dlm_debug(void){	struct ocfs2_dlm_debug *dlm_debug;	dlm_debug = kmalloc(sizeof(struct ocfs2_dlm_debug), GFP_KERNEL);	if (!dlm_debug) {		mlog_errno(-ENOMEM);		goto out;	}	kref_init(&dlm_debug->d_refcnt);	INIT_LIST_HEAD(&dlm_debug->d_lockres_tracking);	dlm_debug->d_locking_state = NULL;out:	return dlm_debug;}/* Access to this is arbitrated for us via seq_file->sem. */struct ocfs2_dlm_seq_priv {	struct ocfs2_dlm_debug *p_dlm_debug;	struct ocfs2_lock_res p_iter_res;	struct ocfs2_lock_res p_tmp_res;};static struct ocfs2_lock_res *ocfs2_dlm_next_res(struct ocfs2_lock_res *start,						 struct ocfs2_dlm_seq_priv *priv){	struct ocfs2_lock_res *iter, *ret = NULL;	struct ocfs2_dlm_debug *dlm_debug = priv->p_dlm_debug;	assert_spin_locked(&ocfs2_dlm_tracking_lock);	list_for_each_entry(iter, &start->l_debug_list, l_debug_list) {		/* discover the head of the list */		if (&iter->l_debug_list == &dlm_debug->d_lockres_tracking) {			mlog(0, "End of list found, %p\n", ret);			break;		}		/* We track our "dummy" iteration lockres' by a NULL		 * l_ops field. */		if (iter->l_ops != NULL) {			ret = iter;			break;		}	}	return ret;}static void *ocfs2_dlm_seq_start(struct seq_file *m, loff_t *pos){	struct ocfs2_dlm_seq_priv *priv = m->private;	struct ocfs2_lock_res *iter;	spin_lock(&ocfs2_dlm_tracking_lock);	iter = ocfs2_dlm_next_res(&priv->p_iter_res, priv);	if (iter) {		/* Since lockres' have the lifetime of their container		 * (which can be inodes, ocfs2_supers, etc) we want to		 * copy this out to a temporary lockres while still		 * under the spinlock. Obviously after this we can't		 * trust any pointers on the copy returned, but that's		 * ok as the information we want isn't typically held		 * in them. */		priv->p_tmp_res = *iter;		iter = &priv->p_tmp_res;	}	spin_unlock(&ocfs2_dlm_tracking_lock);	return iter;}static void ocfs2_dlm_seq_stop(struct seq_file *m, void *v){}static void *ocfs2_dlm_seq_next(struct seq_file *m, void *v, loff_t *pos){	struct ocfs2_dlm_seq_priv *priv = m->private;	struct ocfs2_lock_res *iter = v;	struct ocfs2_lock_res *dummy = &priv->p_iter_res;	spin_lock(&ocfs2_dlm_tracking_lock);	iter = ocfs2_dlm_next_res(iter, priv);	list_del_init(&dummy->l_debug_list);	if (iter) {		list_add(&dummy->l_debug_list, &iter->l_debug_list);		priv->p_tmp_res = *iter;		iter = &priv->p_tmp_res;	}	spin_unlock(&ocfs2_dlm_tracking_lock);	return iter;}/* So that debugfs.ocfs2 can determine which format is being used */#define OCFS2_DLM_DEBUG_STR_VERSION 1static int ocfs2_dlm_seq_show(struct seq_file *m, void *v){	int i;	char *lvb;	struct ocfs2_lock_res *lockres = v;	if (!lockres)		return -EINVAL;	seq_printf(m, "0x%x\t", OCFS2_DLM_DEBUG_STR_VERSION);	if (lockres->l_type == OCFS2_LOCK_TYPE_DENTRY)		seq_printf(m, "%.*s%08x\t", OCFS2_DENTRY_LOCK_INO_START - 1,			   lockres->l_name,			   (unsigned int)ocfs2_get_dentry_lock_ino(lockres));	else		seq_printf(m, "%.*s\t", OCFS2_LOCK_ID_MAX_LEN, lockres->l_name);	seq_printf(m, "%d\t"		   "0x%lx\t"		   "0x%x\t"		   "0x%x\t"		   "%u\t"		   "%u\t"		   "%d\t"		   "%d\t",		   lockres->l_level,		   lockres->l_flags,		   lockres->l_action,		   lockres->l_unlock_action,		   lockres->l_ro_holders,		   lockres->l_ex_holders,		   lockres->l_requested,		   lockres->l_blocking);	/* Dump the raw LVB */	lvb = lockres->l_lksb.lvb;	for(i = 0; i < DLM_LVB_LEN; i++)		seq_printf(m, "0x%x\t", lvb[i]);	/* End the line */	seq_printf(m, "\n");	return 0;}static struct seq_operations ocfs2_dlm_seq_ops = {	.start =	ocfs2_dlm_seq_start,	.stop =		ocfs2_dlm_seq_stop,	.next =		ocfs2_dlm_seq_next,	.show =		ocfs2_dlm_seq_show,};static int ocfs2_dlm_debug_release(struct inode *inode, struct file *file){	struct seq_file *seq = (struct seq_file *) file->private_data;	struct ocfs2_dlm_seq_priv *priv = seq->private;	struct ocfs2_lock_res *res = &priv->p_iter_res;	ocfs2_remove_lockres_tracking(res);	ocfs2_put_dlm_debug(priv->p_dlm_debug);	return seq_release_private(inode, file);}static int ocfs2_dlm_debug_open(struct inode *inode, struct file *file){	int ret;	struct ocfs2_dlm_seq_priv *priv;	struct seq_file *seq;	struct ocfs2_super *osb;	priv = kzalloc(sizeof(struct ocfs2_dlm_seq_priv), GFP_KERNEL);	if (!priv) {		ret = -ENOMEM;		mlog_errno(ret);		goto out;	}	osb = inode->i_private;	ocfs2_get_dlm_debug(osb->osb_dlm_debug);	priv->p_dlm_debug = osb->osb_dlm_debug;	INIT_LIST_HEAD(&priv->p_iter_res.l_debug_list);	ret = seq_open(file, &ocfs2_dlm_seq_ops);	if (ret) {		kfree(priv);		mlog_errno(ret);		goto out;	}	seq = (struct seq_file *) file->private_data;	seq->private = priv;	ocfs2_add_lockres_tracking(&priv->p_iter_res,				   priv->p_dlm_debug);out:	return ret;}static const struct file_operations ocfs2_dlm_debug_fops = {	.open =		ocfs2_dlm_debug_open,	.release =	ocfs2_dlm_debug_release,	.read =		seq_read,	.llseek =	seq_lseek,};static int ocfs2_dlm_init_debug(struct ocfs2_super *osb){	int ret = 0;	struct ocfs2_dlm_debug *dlm_debug = osb->osb_dlm_debug;	dlm_debug->d_locking_state = debugfs_create_file("locking_state",							 S_IFREG|S_IRUSR,							 osb->osb_debug_root,							 osb,							 &ocfs2_dlm_debug_fops);	if (!dlm_debug->d_locking_state) {		ret = -EINVAL;		mlog(ML_ERROR,		     "Unable to create locking state debugfs file.\n");		goto out;	}	ocfs2_get_dlm_debug(dlm_debug);out:	return ret;}static void ocfs2_dlm_shutdown_debug(struct ocfs2_super *osb){	struct ocfs2_dlm_debug *dlm_debug = osb->osb_dlm_debug;	if (dlm_debug) {		debugfs_remove(dlm_debug->d_locking_state);		ocfs2_put_dlm_debug(dlm_debug);	}}int ocfs2_dlm_init(struct ocfs2_super *osb){	int status = 0;	u32 dlm_key;	struct dlm_ctxt *dlm = NULL;	mlog_entry_void();	if (ocfs2_mount_local(osb))		goto local;	status = ocfs2_dlm_init_debug(osb);	if (status < 0) {		mlog_errno(status);		goto bail;	}	/* launch vote thread */	osb->vote_task = kthread_run(ocfs2_vote_thread, osb, "ocfs2vote");	if (IS_ERR(osb->vote_task)) {		status = PTR_ERR(osb->vote_task);		osb->vote_task = NULL;		mlog_errno(status);		goto bail;	}	/* used by the dlm code to make message headers unique, each	 * node in this domain must agree on this. */	dlm_key = crc32_le(0, osb->uuid_str, strlen(osb->uuid_str));	/* for now, uuid == domain */	dlm = dlm_register_domain(osb->uuid_str, dlm_key);	if (IS_ERR(dlm)) {		status = PTR_ERR(dlm);		mlog_errno(status);		goto bail;	}	dlm_register_eviction_cb(dlm, &osb->osb_eviction_cb);local:	ocfs2_super_lock_res_init(&osb->osb_super_lockres, osb);	ocfs2_rename_lock_res_init(&osb->osb_rename_lockres, osb);	osb->dlm = dlm;	status = 0;bail:	if (status < 0) {		ocfs2_dlm_shutdown_debug(osb);		if (osb->vote_task)			kthread_stop(osb->vote_task);	}	mlog_exit(status);	return status;}void ocfs2_dlm_shutdown(struct ocfs2_super *osb){	mlog_entry_void();	dlm_unregister_eviction_cb(&osb->osb_eviction_cb);	ocfs2_drop_osb_locks(osb);	if (osb->vote_task) {		kthread_stop(osb->vote_task);		osb->vote_task = NULL;	}	ocfs2_lock_res_free(&osb->osb_super_lockres);	ocfs2_lock_res_free(&osb->osb_rename_lockres);	dlm_unregister_domain(osb->dlm);	osb->dlm = NULL;	ocfs2_dlm_shutdown_debug(osb);	mlog_exit_void();}static void ocfs2_unlock_ast(void *opaque, enum dlm_status status){	struct ocfs2_lock_res *lockres = opaque;	unsigned long flags;	mlog_entry_void();	mlog(0, "UNLOCK AST called on lock %s, action = %d\n", lockres->l_name,	     lockres->l_unlock_action);	spin_lock_irqsave(&lockres->l_lock, flags);	/* We tried to cancel a convert request, but it was already	 * granted. All we want to do here is clear our unlock	 * state. The wake_up call done at the bottom is redundant	 * (ocfs2_prepare_cancel_convert doesn't sleep on this) but doesn't	 * hurt anything anyway */	if (status == DLM_CANCELGRANT &&	    lockres->l_unlock_action == OCFS2_UNLOCK_CANCEL_CONVERT) {		mlog(0, "Got cancelgrant for %s\n", lockres->l_name);		/* We don't clear the busy flag in this case as it		 * should have been cleared by the ast which the dlm		 * has called. */		goto complete_unlock;	}	if (status != DLM_NORMAL) {		mlog(ML_ERROR, "Dlm passes status %d for lock %s, "		     "unlock_action %d\n", status, lockres->l_name,		     lockres->l_unlock_action);		spin_unlock_irqrestore(&lockres->l_lock, flags);		return;	}	switch(lockres->l_unlock_action) {	case OCFS2_UNLOCK_CANCEL_CONVERT:		mlog(0, "Cancel convert success for %s\n", lockres->l_name);		lockres->l_action = OCFS2_AST_INVALID;		break;	case OCFS2_UNLOCK_DROP_LOCK:		lockres->l_level = LKM_IVMODE;		break;	default:		BUG();	}	lockres_clear_flags(lockres, OCFS2_LOCK_BUSY);complete_unlock:	lockres->l_unlock_action = OCFS2_UNLOCK_INVALID;	spin_unlock_irqrestore(&lockres->l_lock, flags);	wake_up(&lockres->l_event);	mlog_exit_void();}static int ocfs2_drop_lock(struct ocfs2_super *osb,			   struct ocfs2_lock_res *lockres){	enum dlm_status status;	unsigned long flags;	int lkm_flags = 0;	/* We didn't get anywhere near actually using this lockres. */	if (!(lockres->l_flags & OCFS2_LOCK_INITI

⌨️ 快捷键说明

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