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

📄 dlmdomain.c

📁 ocfs1.4.1 oracle分布式文件系统
💻 C
📖 第 1 页 / 共 4 页
字号:
	ret = dlm->joining_node == DLM_LOCK_RES_OWNER_UNKNOWN;	spin_unlock(&dlm->spinlock);	return ret;}static void dlm_mark_domain_leaving(struct dlm_ctxt *dlm){	/* Yikes, a double spinlock! I need domain_lock for the dlm	 * state and the dlm spinlock for join state... Sorry! */again:	spin_lock(&dlm_domain_lock);	spin_lock(&dlm->spinlock);	if (dlm->joining_node != DLM_LOCK_RES_OWNER_UNKNOWN) {		mlog(0, "Node %d is joining, we wait on it.\n",			  dlm->joining_node);		spin_unlock(&dlm->spinlock);		spin_unlock(&dlm_domain_lock);		wait_event(dlm->dlm_join_events, dlm_no_joining_node(dlm));		goto again;	}	dlm->dlm_state = DLM_CTXT_LEAVING;	spin_unlock(&dlm->spinlock);	spin_unlock(&dlm_domain_lock);}static void __dlm_print_nodes(struct dlm_ctxt *dlm){	int node = -1;	assert_spin_locked(&dlm->spinlock);	printk(KERN_INFO "ocfs2_dlm: Nodes in domain (\"%s\"): ", dlm->name);	while ((node = find_next_bit(dlm->domain_map, O2NM_MAX_NODES,				     node + 1)) < O2NM_MAX_NODES) {		printk("%d ", node);	}	printk("\n");}static int dlm_exit_domain_handler(struct o2net_msg *msg, u32 len, void *data,				   void **ret_data){	struct dlm_ctxt *dlm = data;	unsigned int node;	struct dlm_exit_domain *exit_msg = (struct dlm_exit_domain *) msg->buf;	mlog_entry("%p %u %p", msg, len, data);	if (!dlm_grab(dlm))		return 0;	node = exit_msg->node_idx;	printk(KERN_INFO "ocfs2_dlm: Node %u leaves domain %s\n", node, dlm->name);	spin_lock(&dlm->spinlock);	clear_bit(node, dlm->domain_map);	__dlm_print_nodes(dlm);	/* notify anything attached to the heartbeat events */	dlm_hb_event_notify_attached(dlm, node, 0);	spin_unlock(&dlm->spinlock);	dlm_put(dlm);	return 0;}static int dlm_send_one_domain_exit(struct dlm_ctxt *dlm,				    unsigned int node){	int status;	struct dlm_exit_domain leave_msg;	mlog(0, "Asking node %u if we can leave the domain %s me = %u\n",		  node, dlm->name, dlm->node_num);	memset(&leave_msg, 0, sizeof(leave_msg));	leave_msg.node_idx = dlm->node_num;	status = o2net_send_message(DLM_EXIT_DOMAIN_MSG, dlm->key,				    &leave_msg, sizeof(leave_msg), node,				    NULL);	mlog(0, "status return %d from o2net_send_message\n", status);	return status;}static void dlm_leave_domain(struct dlm_ctxt *dlm){	int node, clear_node, status;	/* At this point we've migrated away all our locks and won't	 * accept mastership of new ones. The dlm is responsible for	 * almost nothing now. We make sure not to confuse any joining	 * nodes and then commence shutdown procedure. */	spin_lock(&dlm->spinlock);	/* Clear ourselves from the domain map */	clear_bit(dlm->node_num, dlm->domain_map);	while ((node = find_next_bit(dlm->domain_map, O2NM_MAX_NODES,				     0)) < O2NM_MAX_NODES) {		/* Drop the dlm spinlock. This is safe wrt the domain_map.		 * -nodes cannot be added now as the		 *   query_join_handlers knows to respond with OK_NO_MAP		 * -we catch the right network errors if a node is		 *   removed from the map while we're sending him the		 *   exit message. */		spin_unlock(&dlm->spinlock);		clear_node = 1;		status = dlm_send_one_domain_exit(dlm, node);		if (status < 0 &&		    status != -ENOPROTOOPT &&		    status != -ENOTCONN) {			mlog(ML_NOTICE, "Error %d sending domain exit message "			     "to node %d\n", status, node);			/* Not sure what to do here but lets sleep for			 * a bit in case this was a transient			 * error... */			msleep(DLM_DOMAIN_BACKOFF_MS);			clear_node = 0;		}		spin_lock(&dlm->spinlock);		/* If we're not clearing the node bit then we intend		 * to loop back around to try again. */		if (clear_node)			clear_bit(node, dlm->domain_map);	}	spin_unlock(&dlm->spinlock);}int dlm_joined(struct dlm_ctxt *dlm){	int ret = 0;	spin_lock(&dlm_domain_lock);	if (dlm->dlm_state == DLM_CTXT_JOINED)		ret = 1;	spin_unlock(&dlm_domain_lock);	return ret;}int dlm_shutting_down(struct dlm_ctxt *dlm){	int ret = 0;	spin_lock(&dlm_domain_lock);	if (dlm->dlm_state == DLM_CTXT_IN_SHUTDOWN)		ret = 1;	spin_unlock(&dlm_domain_lock);	return ret;}void dlm_unregister_domain(struct dlm_ctxt *dlm){	int leave = 0;	struct dlm_lock_resource *res;	spin_lock(&dlm_domain_lock);	BUG_ON(dlm->dlm_state != DLM_CTXT_JOINED);	BUG_ON(!dlm->num_joins);	dlm->num_joins--;	if (!dlm->num_joins) {		/* We mark it "in shutdown" now so new register		 * requests wait until we've completely left the		 * domain. Don't use DLM_CTXT_LEAVING yet as we still		 * want new domain joins to communicate with us at		 * least until we've completed migration of our		 * resources. */		dlm->dlm_state = DLM_CTXT_IN_SHUTDOWN;		leave = 1;	}	spin_unlock(&dlm_domain_lock);	if (leave) {		mlog(0, "shutting down domain %s\n", dlm->name);		/* We changed dlm state, notify the thread */		dlm_kick_thread(dlm, NULL);		while (dlm_migrate_all_locks(dlm)) {			/* Give dlm_thread time to purge the lockres' */			msleep(500);			mlog(0, "%s: more migration to do\n", dlm->name);		}		/* This list should be empty. If not, print remaining lockres */		if (!list_empty(&dlm->tracking_list)) {			mlog(ML_ERROR, "Following lockres' are still on the "			     "tracking list:\n");			list_for_each_entry(res, &dlm->tracking_list, tracking)				dlm_print_one_lock_resource(res);		}		dlm_mark_domain_leaving(dlm);		dlm_leave_domain(dlm);		dlm_complete_dlm_shutdown(dlm);	}	dlm_put(dlm);}EXPORT_SYMBOL_GPL(dlm_unregister_domain);static int dlm_query_join_proto_check(char *proto_type, int node,				      struct dlm_protocol_version *ours,				      struct dlm_protocol_version *request){	int rc;	struct dlm_protocol_version proto = *request;	if (!dlm_protocol_compare(ours, &proto)) {		mlog(0,		     "node %u wanted to join with %s locking protocol "		     "%u.%u, we respond with %u.%u\n",		     node, proto_type,		     request->pv_major,		     request->pv_minor,		     proto.pv_major, proto.pv_minor);		request->pv_minor = proto.pv_minor;		rc = 0;	} else {		mlog(ML_NOTICE,		     "Node %u wanted to join with %s locking "		     "protocol %u.%u, but we have %u.%u, disallowing\n",		     node, proto_type,		     request->pv_major,		     request->pv_minor,		     ours->pv_major,		     ours->pv_minor);		rc = 1;	}	return rc;}/* * struct dlm_query_join_packet is made up of four one-byte fields.  They * are effectively in big-endian order already.  However, little-endian * machines swap them before putting the packet on the wire (because * query_join's response is a status, and that status is treated as a u32 * on the wire).  Thus, a big-endian and little-endian machines will treat * this structure differently. * * The solution is to have little-endian machines swap the structure when * converting from the structure to the u32 representation.  This will * result in the structure having the correct format on the wire no matter * the host endian format. */static void dlm_query_join_packet_to_wire(struct dlm_query_join_packet *packet,					  u32 *wire){	union dlm_query_join_response response;	response.packet = *packet;	*wire = cpu_to_be32(response.intval);}static void dlm_query_join_wire_to_packet(u32 wire,					  struct dlm_query_join_packet *packet){	union dlm_query_join_response response;	response.intval = cpu_to_be32(wire);	*packet = response.packet;}static int dlm_query_join_handler(struct o2net_msg *msg, u32 len, void *data,				  void **ret_data){	struct dlm_query_join_request *query;	struct dlm_query_join_packet packet = {		.code = JOIN_DISALLOW,	};	struct dlm_ctxt *dlm = NULL;	u32 response;	u8 nodenum;	query = (struct dlm_query_join_request *) msg->buf;	mlog(0, "node %u wants to join domain %s\n", query->node_idx,		  query->domain);	/*	 * If heartbeat doesn't consider the node live, tell it	 * to back off and try again.  This gives heartbeat a chance	 * to catch up.	 */	if (!o2hb_check_node_heartbeating(query->node_idx)) {		mlog(0, "node %u is not in our live map yet\n",		     query->node_idx);		packet.code = JOIN_DISALLOW;		goto respond;	}	packet.code = JOIN_OK_NO_MAP;	spin_lock(&dlm_domain_lock);	dlm = __dlm_lookup_domain_full(query->domain, query->name_len);	if (!dlm)		goto unlock_respond;	/*	 * There is a small window where the joining node may not see the	 * node(s) that just left but still part of the cluster. DISALLOW	 * join request if joining node has different node map.	 */	nodenum=0;	while (nodenum < O2NM_MAX_NODES) {		if (test_bit(nodenum, dlm->domain_map)) {			if (!byte_test_bit(nodenum, query->node_map)) {				mlog(0, "disallow join as node %u does not "				     "have node %u in its nodemap\n",				     query->node_idx, nodenum);				packet.code = JOIN_DISALLOW;				goto unlock_respond;			}		}		nodenum++;	}	/* Once the dlm ctxt is marked as leaving then we don't want	 * to be put in someone's domain map. 	 * Also, explicitly disallow joining at certain troublesome	 * times (ie. during recovery). */	if (dlm && dlm->dlm_state != DLM_CTXT_LEAVING) {		int bit = query->node_idx;		spin_lock(&dlm->spinlock);		if (dlm->dlm_state == DLM_CTXT_NEW &&		    dlm->joining_node == DLM_LOCK_RES_OWNER_UNKNOWN) {			/*If this is a brand new context and we			 * haven't started our join process yet, then			 * the other node won the race. */			packet.code = JOIN_OK_NO_MAP;		} else if (dlm->joining_node != DLM_LOCK_RES_OWNER_UNKNOWN) {			/* Disallow parallel joins. */			packet.code = JOIN_DISALLOW;		} else if (dlm->reco.state & DLM_RECO_STATE_ACTIVE) {			mlog(0, "node %u trying to join, but recovery "			     "is ongoing.\n", bit);			packet.code = JOIN_DISALLOW;		} else if (test_bit(bit, dlm->recovery_map)) {			mlog(0, "node %u trying to join, but it "			     "still needs recovery.\n", bit);			packet.code = JOIN_DISALLOW;		} else if (test_bit(bit, dlm->domain_map)) {			mlog(0, "node %u trying to join, but it "			     "is still in the domain! needs recovery?\n",			     bit);			packet.code = JOIN_DISALLOW;		} else {			/* Alright we're fully a part of this domain			 * so we keep some state as to who's joining			 * and indicate to him that needs to be fixed			 * up. */			/* Make sure we speak compatible locking protocols.  */			if (dlm_query_join_proto_check("DLM", bit,						       &dlm->dlm_locking_proto,						       &query->dlm_proto)) {				packet.code = JOIN_PROTOCOL_MISMATCH;			} else if (dlm_query_join_proto_check("fs", bit,							      &dlm->fs_locking_proto,							      &query->fs_proto)) {				packet.code = JOIN_PROTOCOL_MISMATCH;			} else {				packet.dlm_minor = query->dlm_proto.pv_minor;				packet.fs_minor = query->fs_proto.pv_minor;				packet.code = JOIN_OK;				__dlm_set_joining_node(dlm, query->node_idx);			}		}		spin_unlock(&dlm->spinlock);	}unlock_respond:	spin_unlock(&dlm_domain_lock);respond:	mlog(0, "We respond with %u\n", packet.code);	dlm_query_join_packet_to_wire(&packet, &response);	return response;}static int dlm_assert_joined_handler(struct o2net_msg *msg, u32 len, void *data,				     void **ret_data){	struct dlm_assert_joined *assert;	struct dlm_ctxt *dlm = NULL;	assert = (struct dlm_assert_joined *) msg->buf;	mlog(0, "node %u asserts join on domain %s\n", assert->node_idx,		  assert->domain);	spin_lock(&dlm_domain_lock);	dlm = __dlm_lookup_domain_full(assert->domain, assert->name_len);	/* XXX should we consider no dlm ctxt an error? */	if (dlm) {		spin_lock(&dlm->spinlock);		/* Alright, this node has officially joined our		 * domain. Set him in the map and clean up our		 * leftover join state. */		BUG_ON(dlm->joining_node != assert->node_idx);		set_bit(assert->node_idx, dlm->domain_map);		__dlm_set_joining_node(dlm, DLM_LOCK_RES_OWNER_UNKNOWN);		printk(KERN_INFO "ocfs2_dlm: Node %u joins domain %s\n",		       assert->node_idx, dlm->name);		__dlm_print_nodes(dlm);		/* notify anything attached to the heartbeat events */		dlm_hb_event_notify_attached(dlm, assert->node_idx, 1);		spin_unlock(&dlm->spinlock);	}	spin_unlock(&dlm_domain_lock);	return 0;}static int dlm_cancel_join_handler(struct o2net_msg *msg, u32 len, void *data,				   void **ret_data){	struct dlm_cancel_join *cancel;	struct dlm_ctxt *dlm = NULL;	cancel = (struct dlm_cancel_join *) msg->buf;	mlog(0, "node %u cancels join on domain %s\n", cancel->node_idx,		  cancel->domain);	spin_lock(&dlm_domain_lock);	dlm = __dlm_lookup_domain_full(cancel->domain, cancel->name_len);	if (dlm) {		spin_lock(&dlm->spinlock);		/* Yikes, this guy wants to cancel his join. No		 * problem, we simply cleanup our join state. */		BUG_ON(dlm->joining_node != cancel->node_idx);		__dlm_set_joining_node(dlm, DLM_LOCK_RES_OWNER_UNKNOWN);		spin_unlock(&dlm->spinlock);	}	spin_unlock(&dlm_domain_lock);	return 0;}static int dlm_send_one_join_cancel(struct dlm_ctxt *dlm,				    unsigned int node){	int status;	struct dlm_cancel_join cancel_msg;

⌨️ 快捷键说明

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