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

📄 dlmglue.c

📁 ocfs1.2.7 源码
💻 C
📖 第 1 页 / 共 5 页
字号:
	}	status = ocfs2_read_block(OCFS2_SB(inode->i_sb),				  OCFS2_I(inode)->ip_blkno,				  ret_bh,				  OCFS2_BH_CACHED,				  inode);	if (status < 0)		mlog_errno(status);	return status;}/* * returns < 0 error if the callback will never be called, otherwise * the result of the lock will be communicated via the callback. */int ocfs2_meta_lock_full(struct inode *inode,			 struct ocfs2_journal_handle *handle,			 struct buffer_head **ret_bh,			 int ex,			 int flags,			 ocfs2_lock_callback cb,			 unsigned long cb_data){	int status, level, dlm_flags, acquired;	struct ocfs2_lock_res *lockres = NULL;	struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);	struct buffer_head *local_bh = NULL;	BUG_ON(!inode);	mlog_entry_void();	mlog(0, "inode %"MLFu64", take %s META lock\n",	     OCFS2_I(inode)->ip_blkno,	     ex ? "EXMODE" : "PRMODE");	status = 0;	acquired = 0;	/* We'll allow faking a readonly metadata lock for	 * rodevices. */	if (ocfs2_is_hard_readonly(osb)) {		if (ex)			status = -EROFS;		goto bail;	}	if (ocfs2_mount_local(osb))		goto local;	if (!(flags & OCFS2_META_LOCK_RECOVERY))		wait_event(osb->recovery_event,			   ocfs2_node_map_is_empty(osb, &osb->recovery_map));	lockres = &OCFS2_I(inode)->ip_meta_lockres;	level = ex ? LKM_EXMODE : LKM_PRMODE;	dlm_flags = 0;	if (flags & OCFS2_META_LOCK_NOQUEUE)		dlm_flags |= LKM_NOQUEUE;	status = ocfs2_cluster_lock(osb, lockres, level, dlm_flags, cb,				    cb_data);	if (status < 0) {		if (status != -EAGAIN && status != -EIOCBRETRY)			mlog_errno(status);		goto bail;	}	/* Notify the error cleanup path to drop the cluster lock. */	acquired = 1;	/* We wait twice because a node may have died while we were in	 * the lower dlm layers. The second time though, we've	 * committed to owning this lock so we don't allow signals to	 * abort the operation. */	if (!(flags & OCFS2_META_LOCK_RECOVERY))		wait_event(osb->recovery_event,			   ocfs2_node_map_is_empty(osb, &osb->recovery_map));local:	/* This is fun. The caller may want a bh back, or it may	 * not. ocfs2_meta_lock_update definitely wants one in, but	 * may or may not read one, depending on what's in the	 * LVB. The result of all of this is that we've *only* gone to	 * disk if we have to, so the complexity is worthwhile. */	status = ocfs2_meta_lock_update(inode, &local_bh);	if (status < 0) {		if (status != -ENOENT)			mlog_errno(status);		goto bail;	}	if (ret_bh) {		status = ocfs2_assign_bh(inode, ret_bh, local_bh);		if (status < 0) {			mlog_errno(status);			goto bail;		}	}	if (handle) {		status = ocfs2_handle_add_lock(handle, inode);		if (status < 0)			mlog_errno(status);	}bail:	if (status < 0) {		if (ret_bh && (*ret_bh)) {			brelse(*ret_bh);			*ret_bh = NULL;		}		if (acquired)			ocfs2_meta_unlock(inode, ex);	}	if (local_bh)		brelse(local_bh);	mlog_exit(status);	return status;}void ocfs2_meta_unlock(struct inode *inode,		       int ex){	int level = ex ? LKM_EXMODE : LKM_PRMODE;	struct ocfs2_lock_res *lockres = &OCFS2_I(inode)->ip_meta_lockres;	struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);	mlog_entry_void();	mlog(0, "inode %"MLFu64" drop %s META lock\n",	     OCFS2_I(inode)->ip_blkno,	     ex ? "EXMODE" : "PRMODE");	if (!ocfs2_is_hard_readonly(osb) && !ocfs2_mount_local(osb))		ocfs2_cluster_unlock(OCFS2_SB(inode->i_sb), lockres, level);	mlog_exit_void();}int ocfs2_super_lock(struct ocfs2_super *osb,		     int ex){	int status;	int level = ex ? LKM_EXMODE : LKM_PRMODE;	struct ocfs2_lock_res *lockres = &osb->osb_super_lockres;	struct buffer_head *bh;	struct ocfs2_slot_info *si = osb->slot_info;	mlog_entry_void();	if (ocfs2_is_hard_readonly(osb))		return -EROFS;	if (ocfs2_mount_local(osb))		return 0;	status = ocfs2_cluster_lock(osb, lockres, level, 0, NULL, 0);	if (status < 0) {		mlog_errno(status);		goto bail;	}	/* The super block lock path is really in the best position to	 * know when resources covered by the lock need to be	 * refreshed, so we do it here. Of course, making sense of	 * everything is up to the caller :) */	status = ocfs2_should_refresh_lock_res(lockres);	if (status < 0) {		mlog_errno(status);		goto bail;	}	if (status) {		bh = si->si_bh;		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, NULL, 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);}/* 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, ocfs2_dlm_debug_free);	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"		   "%.*s\t"		   "%d\t"		   "0x%lx\t"		   "0x%x\t"		   "0x%x\t"		   "%u\t"		   "%u\t"		   "%d\t"		   "%d\t",		   OCFS2_DLM_DEBUG_STR_VERSION,		   OCFS2_LOCK_ID_MAX_LEN, lockres->l_name,		   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;	}#ifdef INODE_HAS_PRIVATE	osb = inode->i_private;#else	osb = (struct ocfs2_super *) inode->u.generic_ip;#endif	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 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;	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;	}

⌨️ 快捷键说明

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