📄 vote.c
字号:
spin_unlock(&osb->net_response_lock);}static int ocfs2_broadcast_vote(struct ocfs2_super *osb, struct ocfs2_vote_msg *request, unsigned int response_id, int *response, struct ocfs2_net_response_cb *callback){ int status, i, remote_err; struct ocfs2_net_wait_ctxt *w = NULL; int dequeued = 0; mlog_entry_void(); w = ocfs2_new_net_wait_ctxt(response_id); if (!w) { status = -ENOMEM; mlog_errno(status); goto bail; } w->n_callback = callback; /* we're pretty much ready to go at this point, and this fills * in n_response which we need anyway... */ ocfs2_queue_net_wait_ctxt(osb, w); i = ocfs2_node_map_iterate(osb, &osb->mounted_map, 0); while (i != O2NM_INVALID_NODE_NUM) { if (i != osb->node_num) { mlog(0, "trying to send request to node %i\n", i); ocfs2_node_map_set_bit(osb, &w->n_node_map, i); remote_err = 0; status = o2net_send_message(OCFS2_MESSAGE_TYPE_VOTE, osb->net_key, request, sizeof(*request), i, &remote_err); if (status == -ETIMEDOUT) { mlog(0, "remote node %d timed out!\n", i); status = -EAGAIN; goto bail; } if (remote_err < 0) { status = remote_err; mlog(0, "remote error %d on node %d!\n", remote_err, i); mlog_errno(status); goto bail; } if (status < 0) { mlog_errno(status); goto bail; } } i++; i = ocfs2_node_map_iterate(osb, &osb->mounted_map, i); mlog(0, "next is %d, i am %d\n", i, osb->node_num); } mlog(0, "done sending, now waiting on responses...\n"); wait_event(w->n_event, ocfs2_node_map_is_empty(osb, &w->n_node_map)); ocfs2_dequeue_net_wait_ctxt(osb, w); dequeued = 1; *response = w->n_response; status = 0;bail: if (w) { if (!dequeued) ocfs2_dequeue_net_wait_ctxt(osb, w); kfree(w); } mlog_exit(status); return status;}static struct ocfs2_vote_msg * ocfs2_new_vote_request(struct ocfs2_super *osb, u64 blkno, unsigned int generation, enum ocfs2_vote_request type){ struct ocfs2_vote_msg *request; struct ocfs2_msg_hdr *hdr; BUG_ON(!ocfs2_is_valid_vote_request(type)); request = kzalloc(sizeof(*request), GFP_NOFS); if (!request) { mlog_errno(-ENOMEM); } else { hdr = &request->v_hdr; hdr->h_node_num = cpu_to_be32(osb->node_num); hdr->h_request = cpu_to_be32(type); hdr->h_blkno = cpu_to_be64(blkno); hdr->h_generation = cpu_to_be32(generation); } return request;}/* Complete the buildup of a new vote request and process the * broadcast return value. */static int ocfs2_do_request_vote(struct ocfs2_super *osb, struct ocfs2_vote_msg *request, struct ocfs2_net_response_cb *callback){ int status, response = -EBUSY; unsigned int response_id; struct ocfs2_msg_hdr *hdr; response_id = ocfs2_new_response_id(osb); hdr = &request->v_hdr; hdr->h_response_id = cpu_to_be32(response_id); status = ocfs2_broadcast_vote(osb, request, response_id, &response, callback); if (status < 0) { mlog_errno(status); goto bail; } status = response;bail: return status;}int ocfs2_request_mount_vote(struct ocfs2_super *osb){ int status; struct ocfs2_vote_msg *request = NULL; request = ocfs2_new_vote_request(osb, 0ULL, 0, OCFS2_VOTE_REQ_MOUNT); if (!request) { status = -ENOMEM; goto bail; } status = -EAGAIN; while (status == -EAGAIN) { if (!(osb->s_mount_opt & OCFS2_MOUNT_NOINTR) && signal_pending(current)) { status = -ERESTARTSYS; goto bail; } if (ocfs2_node_map_is_only(osb, &osb->mounted_map, osb->node_num)) { status = 0; goto bail; } status = ocfs2_do_request_vote(osb, request, NULL); }bail: kfree(request); return status;}int ocfs2_request_umount_vote(struct ocfs2_super *osb){ int status; struct ocfs2_vote_msg *request = NULL; request = ocfs2_new_vote_request(osb, 0ULL, 0, OCFS2_VOTE_REQ_UMOUNT); if (!request) { status = -ENOMEM; goto bail; } status = -EAGAIN; while (status == -EAGAIN) { /* Do not check signals on this vote... We really want * this one to go all the way through. */ if (ocfs2_node_map_is_only(osb, &osb->mounted_map, osb->node_num)) { status = 0; goto bail; } status = ocfs2_do_request_vote(osb, request, NULL); }bail: kfree(request); return status;}/* TODO: This should eventually be a hash table! */static struct ocfs2_net_wait_ctxt * __ocfs2_find_net_wait_ctxt(struct ocfs2_super *osb, u32 response_id){ struct list_head *p; struct ocfs2_net_wait_ctxt *w = NULL; list_for_each(p, &osb->net_response_list) { w = list_entry(p, struct ocfs2_net_wait_ctxt, n_list); if (response_id == w->n_response_id) break; w = NULL; } return w;}/* Translate response codes into local node errno values */static inline int ocfs2_translate_response(int response){ int ret; switch (response) { case OCFS2_RESPONSE_OK: ret = 0; break; case OCFS2_RESPONSE_BUSY: ret = -EBUSY; break; default: ret = -EINVAL; } return ret;}static int ocfs2_handle_response_message(struct o2net_msg *msg, u32 len, void *data, void **ret_data){ unsigned int response_id, node_num; int response_status; struct ocfs2_super *osb = data; struct ocfs2_response_msg *resp; struct ocfs2_net_wait_ctxt * w; struct ocfs2_net_response_cb *resp_cb; resp = (struct ocfs2_response_msg *) msg->buf; response_id = be32_to_cpu(resp->r_hdr.h_response_id); node_num = be32_to_cpu(resp->r_hdr.h_node_num); response_status = ocfs2_translate_response(be32_to_cpu(resp->r_response)); mlog(0, "received response message:\n"); mlog(0, "h_response_id = %u\n", response_id); mlog(0, "h_request = %u\n", be32_to_cpu(resp->r_hdr.h_request)); mlog(0, "h_blkno = %llu\n", (unsigned long long)be64_to_cpu(resp->r_hdr.h_blkno)); mlog(0, "h_generation = %u\n", be32_to_cpu(resp->r_hdr.h_generation)); mlog(0, "h_node_num = %u\n", node_num); mlog(0, "r_response = %d\n", response_status); spin_lock(&osb->net_response_lock); w = __ocfs2_find_net_wait_ctxt(osb, response_id); if (!w) { mlog(0, "request not found!\n"); goto bail; } resp_cb = w->n_callback; if (response_status && (!w->n_response)) { /* we only really need one negative response so don't * set it twice. */ w->n_response = response_status; } if (resp_cb) { spin_unlock(&osb->net_response_lock); resp_cb->rc_cb(resp_cb->rc_priv, resp); spin_lock(&osb->net_response_lock); } __ocfs2_mark_node_responded(osb, w, node_num);bail: spin_unlock(&osb->net_response_lock); return 0;}static int ocfs2_handle_vote_message(struct o2net_msg *msg, u32 len, void *data, void **ret_data){ int status; struct ocfs2_super *osb = data; struct ocfs2_vote_work *work; work = kmalloc(sizeof(struct ocfs2_vote_work), GFP_NOFS); if (!work) { status = -ENOMEM; mlog_errno(status); goto bail; } INIT_LIST_HEAD(&work->w_list); memcpy(&work->w_msg, msg->buf, sizeof(struct ocfs2_vote_msg)); mlog(0, "scheduling vote request:\n"); mlog(0, "h_response_id = %u\n", be32_to_cpu(work->w_msg.v_hdr.h_response_id)); mlog(0, "h_request = %u\n", be32_to_cpu(work->w_msg.v_hdr.h_request)); mlog(0, "h_blkno = %llu\n", (unsigned long long)be64_to_cpu(work->w_msg.v_hdr.h_blkno)); mlog(0, "h_generation = %u\n", be32_to_cpu(work->w_msg.v_hdr.h_generation)); mlog(0, "h_node_num = %u\n", be32_to_cpu(work->w_msg.v_hdr.h_node_num)); spin_lock(&osb->vote_task_lock); list_add_tail(&work->w_list, &osb->vote_list); osb->vote_count++; spin_unlock(&osb->vote_task_lock); ocfs2_kick_vote_thread(osb); status = 0;bail: return status;}void ocfs2_unregister_net_handlers(struct ocfs2_super *osb){ if (!osb->net_key) return; o2net_unregister_handler_list(&osb->osb_net_handlers); if (!list_empty(&osb->net_response_list)) mlog(ML_ERROR, "net response list not empty!\n"); osb->net_key = 0;}int ocfs2_register_net_handlers(struct ocfs2_super *osb){ int status = 0; if (ocfs2_mount_local(osb)) return 0; status = o2net_register_handler(OCFS2_MESSAGE_TYPE_RESPONSE, osb->net_key, sizeof(struct ocfs2_response_msg), ocfs2_handle_response_message, osb, NULL, &osb->osb_net_handlers); if (status) { mlog_errno(status); goto bail; } status = o2net_register_handler(OCFS2_MESSAGE_TYPE_VOTE, osb->net_key, sizeof(struct ocfs2_vote_msg), ocfs2_handle_vote_message, osb, NULL, &osb->osb_net_handlers); if (status) { mlog_errno(status); goto bail; }bail: if (status < 0) ocfs2_unregister_net_handlers(osb); return status;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -