4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
35 extern md_mn_msg_tbl_entry_t msg_table
[];
38 * When contacting the local rpc.mdcommd we always want to do that using
39 * the IPv4 version of localhost.
41 #define LOCALHOST_IPv4 "127.0.0.1"
44 mdmn_get_message_class(md_mn_msgtype_t msgtype
)
46 return (msg_table
[msgtype
].mte_class
);
50 mdmn_get_handler(md_mn_msgtype_t msgtype
))
51 (md_mn_msg_t
*msg
, uint_t flags
, md_mn_result_t
*res
)
53 return (msg_table
[msgtype
].mte_handler
);
57 mdmn_get_submessage_generator(md_mn_msgtype_t msgtype
))
58 (md_mn_msg_t
*msg
, md_mn_msg_t
**msglist
)
60 return (msg_table
[msgtype
].mte_smgen
);
64 mdmn_get_timeout(md_mn_msgtype_t msgtype
)
66 return (msg_table
[msgtype
].mte_timeout
);
71 ldump_msg(char *prefix
, md_mn_msg_t
*msg
)
73 (void) fprintf(stderr
, "%s &msg = 0x%x\n", prefix
, (uint_t
)msg
);
74 (void) fprintf(stderr
, "%s ID = (%d, 0x%llx-%d)\n", prefix
,
75 MSGID_ELEMS(msg
->msg_msgid
));
76 (void) fprintf(stderr
, "%s sender = %d\n", prefix
, msg
->msg_sender
);
77 (void) fprintf(stderr
, "%s flags = 0x%x\n",
78 prefix
, msg
->msg_flags
);
79 (void) fprintf(stderr
, "%s setno = %d\n", prefix
, msg
->msg_setno
);
80 (void) fprintf(stderr
, "%s recipient = %d\n",
81 prefix
, msg
->msg_recipient
);
82 (void) fprintf(stderr
, "%s type = %d\n", prefix
, msg
->msg_type
);
83 (void) fprintf(stderr
, "%s size = %d\n",
84 prefix
, msg
->msg_event_size
);
87 #define COMMD_PROGNAME "rpc.mdcommd"
89 extern uint_t
meta_rpc_err_mask(void);
92 * If a clnt_call gets an RPC error, force the message out here with details.
93 * This would be nice to send to commd_debug(), but we can't call rpc.mdcommd
97 mdmn_handle_RPC_error(CLIENT
*clnt
, char *ident
, md_mn_nodeid_t nid
)
100 * This is sized for a max message which would look like this:
101 * "mdmn_wakeup_initiator: rpc.mdcommd node 4294967295"
106 CLNT_GETERR((CLIENT
*) clnt
, &e
);
107 if (meta_rpc_err_mask() & (1 << e
.re_status
)) {
109 (void) snprintf(errstr
, sizeof (errstr
),
110 "%s: %s node (local)", ident
, COMMD_PROGNAME
);
112 (void) snprintf(errstr
, sizeof (errstr
),
113 "%s: %s node %d", ident
, COMMD_PROGNAME
, nid
);
115 syslog(LOG_WARNING
, "mdmn_handle_RPC_error: %s",
116 clnt_sperror(clnt
, errstr
));
120 /* Default timeout can be changed using clnt_control() */
121 static struct timeval TIMEOUT
= { 25, 0 };
124 mdmn_send_2(argp
, clnt
, nid
)
130 md_mn_result_t
*clnt_res
= Zalloc(sizeof (md_mn_result_t
));
132 res
= clnt_call(clnt
, mdmn_send
,
133 (xdrproc_t
)xdr_md_mn_msg_t
, (caddr_t
)argp
,
134 (xdrproc_t
)xdr_md_mn_result_t
, (caddr_t
)clnt_res
, TIMEOUT
);
136 if (res
== RPC_SUCCESS
) {
139 mdmn_handle_RPC_error(clnt
, "mdmn_send", nid
);
145 mdmn_work_2(argp
, clnt
, nid
)
151 int *clnt_res
= Zalloc(sizeof (int));
153 res
= clnt_call(clnt
, mdmn_work
,
154 (xdrproc_t
)xdr_md_mn_msg_t
, (caddr_t
)argp
,
155 (xdrproc_t
)xdr_int
, (caddr_t
)clnt_res
, TIMEOUT
);
157 if (res
== RPC_SUCCESS
) {
160 mdmn_handle_RPC_error(clnt
, "mdmn_work", nid
);
166 mdmn_wakeup_initiator_2(argp
, clnt
, nid
)
167 md_mn_result_t
*argp
;
172 int *clnt_res
= Zalloc(sizeof (int));
174 res
= clnt_call(clnt
, mdmn_wakeup_initiator
,
175 (xdrproc_t
)xdr_md_mn_result_t
, (caddr_t
)argp
,
176 (xdrproc_t
)xdr_int
, (caddr_t
)clnt_res
, TIMEOUT
);
178 if (res
== RPC_SUCCESS
) {
181 mdmn_handle_RPC_error(clnt
, "mdmn_wakeup_initiator", nid
);
187 mdmn_wakeup_master_2(argp
, clnt
, nid
)
188 md_mn_result_t
*argp
;
193 int *clnt_res
= Zalloc(sizeof (int));
195 res
= clnt_call(clnt
, mdmn_wakeup_master
,
196 (xdrproc_t
)xdr_md_mn_result_t
, (caddr_t
)argp
,
197 (xdrproc_t
)xdr_int
, (caddr_t
)clnt_res
, TIMEOUT
);
199 if (res
== RPC_SUCCESS
) {
202 mdmn_handle_RPC_error(clnt
, "mdmn_wakeup_master", nid
);
208 mdmn_comm_lock_2(argp
, clnt
, nid
)
209 md_mn_set_and_class_t
*argp
;
214 int *clnt_res
= Zalloc(sizeof (int));
216 res
= clnt_call(clnt
, mdmn_comm_lock
,
217 (xdrproc_t
)xdr_md_mn_set_and_class_t
, (caddr_t
)argp
,
218 (xdrproc_t
)xdr_int
, (caddr_t
)clnt_res
, TIMEOUT
);
220 if (res
== RPC_SUCCESS
) {
223 mdmn_handle_RPC_error(clnt
, "mdmn_comm_lock", nid
);
229 mdmn_comm_unlock_2(argp
, clnt
, nid
)
230 md_mn_set_and_class_t
*argp
;
235 int *clnt_res
= Zalloc(sizeof (int));
237 res
= clnt_call(clnt
, mdmn_comm_unlock
,
238 (xdrproc_t
)xdr_md_mn_set_and_class_t
, (caddr_t
)argp
,
239 (xdrproc_t
)xdr_int
, (caddr_t
)clnt_res
, TIMEOUT
);
241 if (res
== RPC_SUCCESS
) {
244 mdmn_handle_RPC_error(clnt
, "mdmn_comm_unlock", nid
);
250 mdmn_comm_suspend_2(argp
, clnt
, nid
)
251 md_mn_set_and_class_t
*argp
;
256 int *clnt_res
= Zalloc(sizeof (int));
258 res
= clnt_call(clnt
, mdmn_comm_suspend
,
259 (xdrproc_t
)xdr_md_mn_set_and_class_t
, (caddr_t
)argp
,
260 (xdrproc_t
)xdr_int
, (caddr_t
)clnt_res
, TIMEOUT
);
262 if (res
== RPC_SUCCESS
) {
265 mdmn_handle_RPC_error(clnt
, "mdmn_comm_suspend", nid
);
271 mdmn_comm_resume_2(argp
, clnt
, nid
)
272 md_mn_set_and_class_t
*argp
;
277 int *clnt_res
= Zalloc(sizeof (int));
279 res
= clnt_call(clnt
, mdmn_comm_resume
,
280 (xdrproc_t
)xdr_md_mn_set_and_class_t
, (caddr_t
)argp
,
281 (xdrproc_t
)xdr_int
, (caddr_t
)clnt_res
, TIMEOUT
);
283 if (res
== RPC_SUCCESS
) {
286 mdmn_handle_RPC_error(clnt
, "mdmn_comm_resume", nid
);
292 mdmn_comm_reinit_set_2(argp
, clnt
, nid
)
298 int *clnt_res
= Zalloc(sizeof (int));
300 res
= clnt_call(clnt
, mdmn_comm_reinit_set
,
301 (xdrproc_t
)xdr_set_t
, (caddr_t
)argp
,
302 (xdrproc_t
)xdr_int
, (caddr_t
)clnt_res
, TIMEOUT
);
304 if (res
== RPC_SUCCESS
) {
307 mdmn_handle_RPC_error(clnt
, "mdmn_comm_reinit_set", nid
);
313 mdmn_comm_msglock_2(argp
, clnt
, nid
)
314 md_mn_type_and_lock_t
*argp
;
319 int *clnt_res
= Zalloc(sizeof (int));
321 res
= clnt_call(clnt
, mdmn_comm_msglock
,
322 (xdrproc_t
)xdr_md_mn_type_and_lock_t
, (caddr_t
)argp
,
323 (xdrproc_t
)xdr_int
, (caddr_t
)clnt_res
, TIMEOUT
);
325 if (res
== RPC_SUCCESS
) {
328 mdmn_handle_RPC_error(clnt
, "mdmn_comm_msglock", nid
);
334 #define USECS_PER_TICK 10000
338 * Let the kernel create a clusterwide unique message ID
340 * returns 0 on success
345 mdmn_create_msgid(md_mn_msgid_t
*msgid
)
347 md_error_t mde
= mdnullerror
;
350 return (1); /* failure */
353 if (metaioctl(MD_IOCGUNIQMSGID
, msgid
, &mde
, NULL
) != 0) {
354 msgid
->mid_nid
= ~0u;
355 msgid
->mid_time
= 0LL;
356 return (1); /* failure */
360 * mid_smid and mid_oclass are only used for submessages.
361 * mdmn_create_msgid is never called for submessages, as they inherit
362 * the message ID from their parent.
363 * Thus we can safely null out the following fields.
366 msgid
->mid_oclass
= 0;
368 /* if the node_id is not set yet, somethings seems to be wrong */
369 if (msgid
->mid_nid
== ~0u) {
370 return (1); /* failure */
373 return (0); /* success */
377 copy_result(md_mn_result_t
*res
)
379 md_mn_result_t
*nres
;
380 nres
= Zalloc(sizeof (md_mn_result_t
));
381 /* It's MSGID_COPY(from, to); */
382 MSGID_COPY(&(res
->mmr_msgid
), &(nres
->mmr_msgid
));
383 nres
->mmr_msgtype
= res
->mmr_msgtype
;
384 nres
->mmr_setno
= res
->mmr_setno
;
385 nres
->mmr_flags
= res
->mmr_flags
;
386 nres
->mmr_sender
= res
->mmr_sender
;
387 nres
->mmr_failing_node
= res
->mmr_failing_node
;
388 nres
->mmr_comm_state
= res
->mmr_comm_state
;
389 nres
->mmr_exitval
= res
->mmr_exitval
;
390 nres
->mmr_out_size
= res
->mmr_out_size
;
391 nres
->mmr_err_size
= res
->mmr_err_size
;
392 if (res
->mmr_out_size
> 0) {
393 nres
->mmr_out
= Zalloc(res
->mmr_out_size
);
394 bcopy(res
->mmr_out
, nres
->mmr_out
, res
->mmr_out_size
);
396 if (res
->mmr_err_size
> 0) {
397 nres
->mmr_err
= Zalloc(res
->mmr_err_size
);
398 bcopy(res
->mmr_err
, nres
->mmr_err
, res
->mmr_err_size
);
400 if (res
->mmr_ep
.host
!= '\0') {
401 nres
->mmr_ep
.host
= strdup(res
->mmr_ep
.host
);
403 if (res
->mmr_ep
.extra
!= '\0') {
404 nres
->mmr_ep
.extra
= strdup(res
->mmr_ep
.extra
);
406 if (res
->mmr_ep
.name
!= '\0') {
407 nres
->mmr_ep
.name
= strdup(res
->mmr_ep
.name
);
413 free_result(md_mn_result_t
*res
)
415 if (res
->mmr_out_size
> 0) {
418 if (res
->mmr_err_size
> 0) {
421 if (res
->mmr_ep
.host
!= '\0') {
422 Free(res
->mmr_ep
.host
);
424 if (res
->mmr_ep
.extra
!= '\0') {
425 Free(res
->mmr_ep
.extra
);
427 if (res
->mmr_ep
.name
!= '\0') {
428 Free(res
->mmr_ep
.name
);
434 /* allocate a new message and copy a given message into it */
436 copy_msg(md_mn_msg_t
*msg
, md_mn_msg_t
*dest
)
443 nmsg
= Zalloc(sizeof (md_mn_msg_t
));
445 if (nmsg
->msg_event_data
== NULL
) {
446 nmsg
->msg_event_data
= Zalloc(msg
->msg_event_size
);
448 /* It's MSGID_COPY(from, to); */
449 MSGID_COPY(&(msg
->msg_msgid
), &(nmsg
->msg_msgid
));
450 nmsg
->msg_sender
= msg
->msg_sender
;
451 nmsg
->msg_flags
= msg
->msg_flags
;
452 nmsg
->msg_setno
= msg
->msg_setno
;
453 nmsg
->msg_type
= msg
->msg_type
;
454 nmsg
->msg_recipient
= msg
->msg_recipient
;
455 nmsg
->msg_event_size
= msg
->msg_event_size
;
456 if (msg
->msg_event_size
> 0) {
457 bcopy(msg
->msg_event_data
, nmsg
->msg_event_data
,
458 msg
->msg_event_size
);
464 copy_msg_2(md_mn_msg_t
*msg
, md_mn_msg_od_t
*msgod
, int direction
)
466 assert((direction
== MD_MN_COPY_TO_ONDISK
) ||
467 (direction
== MD_MN_COPY_TO_INCORE
));
469 if (direction
== MD_MN_COPY_TO_ONDISK
) {
470 MSGID_COPY(&(msg
->msg_msgid
), &(msgod
->msg_msgid
));
471 msgod
->msg_sender
= msg
->msg_sender
;
472 msgod
->msg_flags
= msg
->msg_flags
;
473 msgod
->msg_setno
= msg
->msg_setno
;
474 msgod
->msg_type
= msg
->msg_type
;
475 msgod
->msg_recipient
= msg
->msg_recipient
;
476 msgod
->msg_od_event_size
= msg
->msg_event_size
;
477 /* paranoid checks */
478 if (msg
->msg_event_size
!= 0 && msg
->msg_event_data
!= NULL
)
479 bcopy(msg
->msg_event_data
,
480 &msgod
->msg_od_event_data
[0], msg
->msg_event_size
);
482 MSGID_COPY(&(msgod
->msg_msgid
), &(msg
->msg_msgid
));
483 msg
->msg_sender
= msgod
->msg_sender
;
484 msg
->msg_flags
= msgod
->msg_flags
;
485 msg
->msg_setno
= msgod
->msg_setno
;
486 msg
->msg_type
= msgod
->msg_type
;
487 msg
->msg_recipient
= msgod
->msg_recipient
;
488 msg
->msg_event_size
= msgod
->msg_od_event_size
;
489 if (msg
->msg_event_data
== NULL
)
490 msg
->msg_event_data
= Zalloc(msg
->msg_event_size
);
492 bcopy(&msgod
->msg_od_event_data
[0],
493 msg
->msg_event_data
, msgod
->msg_od_event_size
);
499 free_msg(md_mn_msg_t
*msg
)
501 if (msg
->msg_event_size
> 0) {
502 Free(msg
->msg_event_data
);
508 /* The following declarations are only for the next two routines */
510 md_mn_client_list_t
*mdmn_clients
;
513 #define MNGLC_INIT_ONLY 0x0001
514 #define MNGLC_FOR_REAL 0x0002
516 * mdmn_get_local_clnt(flag)
517 * If there is a client in the free pool, get one,
518 * If no client is available, create one.
519 * Every multithreaded application that uses mdmn_send_message must call it
520 * single threaded first with special flags so we do the initialization
521 * stuff in a safe environment.
523 * Input: MNGLC_INIT_ONLY: just initializes the mutex
524 * MNGLC_FOR_REAL : do real work
526 * An rpc client for sending rpc requests to the local commd
527 * NULL in case of an error
531 mdmn_get_local_clnt(uint_t flag
)
533 CLIENT
*local_daemon
;
534 static int inited
= 0;
535 md_mn_client_list_t
*tmp
;
538 (void) mutex_init(&mcl_mutex
, USYNC_THREAD
, NULL
);
542 if (flag
== MNGLC_INIT_ONLY
)
543 return ((CLIENT
*)NULL
);
545 (void) mutex_lock(&mcl_mutex
);
546 if (mdmn_clients
== (md_mn_client_list_t
*)NULL
) {
547 /* if there is no entry, create a client and return a it */
548 local_daemon
= meta_client_create(LOCALHOST_IPv4
, MDMN_COMMD
,
552 * If there is an entry from a previous put operation,
553 * remove it from the head of the list and free the list stuff
554 * around it. Then return the client
556 local_daemon
= mdmn_clients
->mcl_clnt
;
558 mdmn_clients
= mdmn_clients
->mcl_next
;
561 (void) mutex_unlock(&mcl_mutex
);
564 if (local_daemon
== (CLIENT
*)NULL
) {
565 clnt_pcreateerror("local_daemon");
568 return (local_daemon
);
572 * mdmn_put_local_clnt()
573 * returns a no longer used client to the pool
575 * Input: an RPC client
579 mdmn_put_local_clnt(CLIENT
*local_daemon
)
581 md_mn_client_list_t
*tmp
;
583 (void) mutex_lock(&mcl_mutex
);
586 mdmn_clients
= (md_mn_client_list_t
*)
587 malloc(sizeof (md_mn_client_list_t
));
588 mdmn_clients
->mcl_clnt
= local_daemon
;
589 mdmn_clients
->mcl_next
= tmp
;
591 (void) mutex_unlock(&mcl_mutex
);
595 * This is the regular interface for sending a message.
596 * This function only passes through all arguments to
597 * mdmn_send_message_with_msgid() and adds a NULL for the message ID.
599 * Normally, you don't have already a message ID for the message you want
600 * to send. Only in case of replaying a previously logged message,
601 * a msgid is already attached to it.
602 * In that case mdmn_send_message_with_msgid() has to be called directly.
604 * The recipient argument is almost always unused, and is therefore typically
605 * set to zero, as zero is an invalid cluster nodeid. The exceptions are the
606 * marking and clearing of the DRL from a node that is not currently the
607 * owner. In these cases, the recipient argument will be the nodeid of the
608 * mirror owner, and MD_MSGF_DIRECTED will be set in the flags. Non-owner
609 * nodes will not receive these messages.
611 * Return values / CAVEAT EMPTOR: see mdmn_send_message_with_msgid()
617 md_mn_msgtype_t type
,
619 md_mn_nodeid_t recipient
,
622 md_mn_result_t
**result
,
625 return (mdmn_send_message_with_msgid(setno
, type
, flags
,
626 recipient
, data
, size
, result
, MD_NULL_MSGID
, ep
));
629 * mdmn_send_message_with_msgid()
630 * Create a message from the given pieces of data and hand it over
631 * to the local commd.
632 * This may fail for various reasons (rpc error / class busy / class locked ...)
633 * Some error types are immediately deadly, others will cause retries
634 * until the request is fulfilled or until the retries are ecxceeded.
636 * In case an error is returned it is up to the user to decide what to do.
640 * 1 if retries1 exceeded
641 * 2 if retries2 exceeded
642 * -1 if connecting to the local daemon failed
643 * -2 if the RPC call to the local daemon failed
644 * -3 if this node hasn't yet joined the set
645 * -4 if any other problem occured
648 * The caller is responsible for calling free_result() when finished with
652 mdmn_send_message_with_msgid(
654 md_mn_msgtype_t type
,
656 md_mn_nodeid_t recipient
,
659 md_mn_result_t
**result
,
660 md_mn_msgid_t
*msgid
,
663 uint_t retry1
, ticks1
, retry2
, ticks2
;
666 CLIENT
*local_daemon
;
667 struct timeval timeout
;
670 md_mn_result_t
*resp
;
673 * Special case for multithreaded applications:
674 * When starting up, the application should call mdmn_send_message
675 * single threaded with all parameters set to NULL.
676 * When we detect this we know, we safely can do initialization
678 * We only check for set and type being zero
680 if ((setno
== 0) && (type
== 0)) {
681 /* do all needed initializations here */
682 (void) mdmn_get_local_clnt(MNGLC_INIT_ONLY
);
683 return (0); /* success */
687 /* did the caller specify space to store the result pointer? */
688 if (result
== (md_mn_result_t
**)NULL
) {
689 syslog(LOG_INFO
, dgettext(TEXT_DOMAIN
,
690 "FATAL, can not allocate result structure\n"));
695 /* Replay messages already have their msgID */
696 if ((flags
& MD_MSGF_REPLAY_MSG
) == 0) {
697 if (mdmn_create_msgid(&msg
.msg_msgid
) != 0) {
698 syslog(LOG_INFO
, dgettext(TEXT_DOMAIN
,
699 "FATAL, can not create message ID\n"));
703 /* in this case a message ID must be specified */
704 assert(msgid
!= MD_NULL_MSGID
);
705 MSGID_COPY(msgid
, &msg
.msg_msgid
);
710 * When setting the flags, additionally apply the
711 * default flags for this message type.
713 msg
.msg_flags
= flags
;
714 msg
.msg_setno
= setno
;
715 msg
.msg_recipient
= recipient
;
717 msg
.msg_event_size
= size
;
718 msg
.msg_event_data
= data
;
721 * For the timeout pick the specific timeout for the message times the
722 * the maximum number of nodes.
723 * This is a better estimate than 1 hour or 3 days or never.
725 timeout
.tv_sec
= mdmn_get_timeout(type
) * NNODES
;
728 if (flags
& MD_MSGF_VERBOSE
) {
729 syslog(LOG_INFO
, "send_message: ID=(%d, 0x%llx-%d)\n",
730 MSGID_ELEMS(msg
.msg_msgid
));
733 /* get an RPC client to the local commd */
734 local_daemon
= mdmn_get_local_clnt(MNGLC_FOR_REAL
);
735 if (local_daemon
== (CLIENT
*)NULL
) {
738 clnt_control(local_daemon
, CLSET_TIMEOUT
, (char *)&timeout
);
740 retry1
= msg_table
[type
].mte_retry1
;
741 ticks1
= msg_table
[type
].mte_ticks1
;
742 retry2
= msg_table
[type
].mte_retry2
;
743 ticks2
= msg_table
[type
].mte_ticks2
;
746 * run that loop until:
748 * - deadly commstate occured
749 * - retries1 or retries2 exceeded
752 *result
= mdmn_send_2(&msg
, local_daemon
, 0);
754 if (resp
!= (md_mn_result_t
*)NULL
) {
756 if (resp
->mmr_comm_state
== MDMNE_ACK
) {
760 /* Hmm... what if there's no handler? */
761 if (resp
->mmr_comm_state
== MDMNE_NO_HANDLER
) {
767 * This node didn't yet join the disk set. It is not
768 * supposed to send any messages then.
769 * This is deadly (no retries)
771 if (resp
->mmr_comm_state
== MDMNE_NOT_JOINED
) {
776 /* these two are deadly too (no retries) */
777 if ((resp
->mmr_comm_state
== MDMNE_NO_WAKEUP_ENTRY
) ||
778 (resp
->mmr_comm_state
== MDMNE_LOG_FAIL
)) {
783 /* Class busy? Use retry1 */
784 if (resp
->mmr_comm_state
== MDMNE_CLASS_BUSY
) {
786 retval
= 1; /* retry1 exceeded */
789 (void) usleep(ticks1
* USECS_PER_TICK
);
792 if (flags
& MD_MSGF_VERBOSE
)
793 (void) printf("#Resend1 ID=(%d, "
795 MSGID_ELEMS(msg
.msg_msgid
));
798 if ((resp
->mmr_comm_state
== MDMNE_CLASS_LOCKED
) ||
799 (resp
->mmr_comm_state
== MDMNE_ABORT
)) {
801 * Be patient, wait for 1 secs and try again.
802 * It's not likely that the ABORT condition ever
803 * goes away, but it won't hurt to retry
809 if (resp
->mmr_comm_state
== MDMNE_SUSPENDED
) {
810 if (flags
& MD_MSGF_FAIL_ON_SUSPEND
) {
811 /* caller wants us to fail here */
813 MDE_DS_NOTNOW_RECONFIG
, setno
,
814 mynode(), mynode(), NULL
);
818 /* wait for 1 secs and try again. */
826 * If we get a NULL back from the rpc call, try to
827 * reinitialize the client.
828 * Depending on retries2 we try again, or not.
831 "send_message: ID=(%d, 0x%llx-%d) resp = NULL\n",
832 MSGID_ELEMS(msg
.msg_msgid
));
834 clnt_destroy(local_daemon
);
835 local_daemon
= mdmn_get_local_clnt(MNGLC_FOR_REAL
);
837 if (local_daemon
== (CLIENT
*)NULL
) {
840 clnt_control(local_daemon
, CLSET_TIMEOUT
,
845 * If we are here, either resp is zero or resp is non-zero
846 * but some commstate not mentioned above occured.
847 * In either case we use retry2
850 syslog(LOG_INFO
, dgettext(TEXT_DOMAIN
,
851 "send_message: (%d, 0x%llx-%d) retry2 exceeded\n"),
852 MSGID_ELEMS(msg
.msg_msgid
));
854 retval
= 2; /* retry2 exceeded */
857 if (flags
& MD_MSGF_VERBOSE
) {
858 syslog(LOG_DEBUG
, dgettext(TEXT_DOMAIN
,
859 "send_message: (%d, 0x%llx-%d) resend on retry2\n"),
860 MSGID_ELEMS(msg
.msg_msgid
));
863 (void) usleep(ticks2
* USECS_PER_TICK
);
865 if (resp
!= (md_mn_result_t
*)NULL
) {
870 mdmn_put_local_clnt(local_daemon
);
875 * suspend the commd for a given set/class combination.
878 * set number or 0 (meaning all sets)
879 * class number or 0 (meaning all classes)
882 * 0 on success (set is suspended and all messages drained)
883 * MDE_DS_COMMDCTL_SUSPEND_NYD if set is not yet drained
884 * MDE_DS_COMMDCTL_SUSPEND_FAIL if any failure occurred
887 mdmn_suspend(set_t setno
, md_mn_msgclass_t
class, long timeout
)
890 CLIENT
*local_daemon
;
891 md_mn_set_and_class_t msc
;
892 md_error_t xep
= mdnullerror
;
894 if ((setno
>= MD_MAXSETS
) || (class >= MD_MN_NCLASSES
)) {
895 return (MDE_DS_COMMDCTL_SUSPEND_FAIL
);
897 local_daemon
= meta_client_create(LOCALHOST_IPv4
, MDMN_COMMD
, TWO
,
899 if (local_daemon
== (CLIENT
*)NULL
) {
900 clnt_pcreateerror("local_daemon");
901 return (MDE_DS_COMMDCTL_SUSPEND_FAIL
);
905 if (cl_sto(local_daemon
, LOCALHOST_IPv4
, timeout
, &xep
) != 0) {
906 clnt_destroy(local_daemon
);
912 msc
.msc_class
= class;
915 resp
= mdmn_comm_suspend_2(&msc
, local_daemon
, 0);
916 clnt_destroy(local_daemon
);
919 return (MDE_DS_COMMDCTL_SUSPEND_FAIL
);
922 if (*resp
== MDMNE_ACK
) {
923 /* set successfully drained, no outstanding messages */
926 if (*resp
!= MDMNE_SET_NOT_DRAINED
) {
927 /* some error occurred */
928 return (MDE_DS_COMMDCTL_SUSPEND_FAIL
);
931 /* still outstanding messages, return not yet drained failure */
932 return (MDE_DS_COMMDCTL_SUSPEND_NYD
);
936 * resume the commd for a given set/class combination.
939 * set number or 0 (meaning all sets)
940 * class number or 0 (meaning all classes)
944 * MDE_DS_COMMDCTL_RESUME_FAIL on failure
947 mdmn_resume(set_t setno
, md_mn_msgclass_t
class, uint_t flags
, long timeout
)
949 md_mn_set_and_class_t msc
;
950 int ret
= MDE_DS_COMMDCTL_RESUME_FAIL
;
952 CLIENT
*local_daemon
;
953 md_error_t xep
= mdnullerror
;
955 if ((setno
>= MD_MAXSETS
) || (class >= MD_MN_NCLASSES
)) {
956 return (MDE_DS_COMMDCTL_RESUME_FAIL
);
958 local_daemon
= meta_client_create(LOCALHOST_IPv4
, MDMN_COMMD
, TWO
,
960 if (local_daemon
== (CLIENT
*)NULL
) {
961 clnt_pcreateerror("local_daemon");
962 return (MDE_DS_COMMDCTL_RESUME_FAIL
);
966 if (cl_sto(local_daemon
, LOCALHOST_IPv4
, timeout
, &xep
) != 0) {
967 clnt_destroy(local_daemon
);
973 msc
.msc_class
= class;
974 msc
.msc_flags
= flags
;
976 resp
= mdmn_comm_resume_2(&msc
, local_daemon
, 0);
979 if (*resp
== MDMNE_ACK
) {
985 clnt_destroy(local_daemon
);
990 * abort all communication
992 * returns void, because: if *this* get's an error what do you want to do?
997 char *dummy
= "abort";
998 md_mn_result_t
*resultp
= NULL
;
999 md_error_t mdne
= mdnullerror
;
1001 (void) mdmn_send_message(0, /* No set is needed for this message */
1002 MD_MN_MSG_ABORT
, MD_MSGF_LOCAL_ONLY
, 0,
1003 dummy
, sizeof (dummy
), &resultp
, &mdne
);
1005 if (resultp
!= NULL
) {
1011 * trigger the reinitialization for a given set.
1013 * Parameter: set number
1020 mdmn_reinit_set(set_t setno
, long timeout
)
1024 CLIENT
*local_daemon
;
1025 md_error_t xep
= mdnullerror
;
1027 if ((setno
== 0) || (setno
>= MD_MAXSETS
)) {
1030 local_daemon
= meta_client_create(LOCALHOST_IPv4
, MDMN_COMMD
, TWO
,
1032 if (local_daemon
== (CLIENT
*)NULL
) {
1033 clnt_pcreateerror("local_daemon");
1038 if (cl_sto(local_daemon
, LOCALHOST_IPv4
, timeout
, &xep
) != 0) {
1039 clnt_destroy(local_daemon
);
1044 resp
= mdmn_comm_reinit_set_2(&setno
, local_daemon
, 0);
1047 if (*resp
== MDMNE_ACK
) {
1053 clnt_destroy(local_daemon
);
1059 * Lock a single message type from being processed on this node
1061 * Parameter: md_mn_msgtype_t msgtype, uint_t locktype
1068 mdmn_msgtype_lock(md_mn_msgtype_t msgtype
, uint_t locktype
)
1072 CLIENT
*local_daemon
;
1073 md_mn_type_and_lock_t mmtl
;
1076 if ((msgtype
== 0) || (msgtype
>= MD_MN_NMESSAGES
)) {
1079 local_daemon
= meta_client_create(LOCALHOST_IPv4
, MDMN_COMMD
, TWO
,
1081 if (local_daemon
== (CLIENT
*)NULL
) {
1082 clnt_pcreateerror("local_daemon");
1085 mmtl
.mmtl_type
= msgtype
;
1086 mmtl
.mmtl_lock
= locktype
;
1088 resp
= mdmn_comm_msglock_2(&mmtl
, local_daemon
, 0);
1091 if (*resp
== MDMNE_ACK
) {
1097 clnt_destroy(local_daemon
);