xref: /onnv-gate/usr/src/cmd/lvm/md_monitord/md_monitord.c (revision 11053:f33a1c7f3155)
10Sstevel@tonic-gate /*
20Sstevel@tonic-gate  * CDDL HEADER START
30Sstevel@tonic-gate  *
40Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*11053SSurya.Prakki@Sun.COM  * Common Development and Distribution License (the "License").
6*11053SSurya.Prakki@Sun.COM  * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate  *
80Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate  * See the License for the specific language governing permissions
110Sstevel@tonic-gate  * and limitations under the License.
120Sstevel@tonic-gate  *
130Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate  *
190Sstevel@tonic-gate  * CDDL HEADER END
200Sstevel@tonic-gate  */
210Sstevel@tonic-gate /*
22*11053SSurya.Prakki@Sun.COM  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
230Sstevel@tonic-gate  * Use is subject to license terms.
240Sstevel@tonic-gate  */
250Sstevel@tonic-gate 
260Sstevel@tonic-gate /*
270Sstevel@tonic-gate  * probedev issues ioctls for all the metadevices
280Sstevel@tonic-gate  */
290Sstevel@tonic-gate 
300Sstevel@tonic-gate #include "md_monitord.h"
310Sstevel@tonic-gate #include <sdssc.h>
320Sstevel@tonic-gate 
330Sstevel@tonic-gate extern char queue_name[];
340Sstevel@tonic-gate boolean_e issue_ioctl = True;
350Sstevel@tonic-gate 
360Sstevel@tonic-gate 
370Sstevel@tonic-gate #define	DEBUG_LEVEL_FORK	9	/* will run in background at all */
380Sstevel@tonic-gate 					/* levels less than DEBUG_LEVEL_FORK */
390Sstevel@tonic-gate 
400Sstevel@tonic-gate /* function prototypes */
410Sstevel@tonic-gate static void usage(void);
420Sstevel@tonic-gate static void catch_sig(int);
430Sstevel@tonic-gate static pid_t enter_daemon_lock(void);
440Sstevel@tonic-gate static void exit_daemon_lock(void);
450Sstevel@tonic-gate static void probe_all_devs(boolean_e, md_error_t *, boolean_e);
460Sstevel@tonic-gate 
470Sstevel@tonic-gate #define	DAEMON_LOCK_FILE "/etc/lvm/.mdmonitord.lock"
480Sstevel@tonic-gate 
490Sstevel@tonic-gate /*
500Sstevel@tonic-gate  * Global variable
510Sstevel@tonic-gate  */
520Sstevel@tonic-gate mdsetname_t	*sp;
530Sstevel@tonic-gate 
540Sstevel@tonic-gate static int hold_daemon_lock;
550Sstevel@tonic-gate static const char *daemon_lock_file = DAEMON_LOCK_FILE;
560Sstevel@tonic-gate static int daemon_lock_fd;
570Sstevel@tonic-gate 
580Sstevel@tonic-gate static int		debug_level;
590Sstevel@tonic-gate static int		logflag;
600Sstevel@tonic-gate static char		*prog;
610Sstevel@tonic-gate static struct itimerval	itimer;
620Sstevel@tonic-gate static boolean_e	probe_started;	/* flag to indicate main is probing */
630Sstevel@tonic-gate 
640Sstevel@tonic-gate static void
usage()650Sstevel@tonic-gate usage() {
660Sstevel@tonic-gate 	(void) fprintf(stderr, gettext(
670Sstevel@tonic-gate 		"usage: mdmonitord [-d <debug_level>] [-t poll time]\n"
680Sstevel@tonic-gate 		    "higher debug levels get progressively more"
690Sstevel@tonic-gate 		    "detailed debug information.\n\n"
700Sstevel@tonic-gate 		    "mdmonitord will run in background if run"
710Sstevel@tonic-gate 		    "with a debug_level less than %d.\n"), DEBUG_LEVEL_FORK);
720Sstevel@tonic-gate 	exit(-1);
730Sstevel@tonic-gate }
740Sstevel@tonic-gate 
750Sstevel@tonic-gate 
760Sstevel@tonic-gate /* common exit function which ensures releasing locks */
770Sstevel@tonic-gate void
monitord_exit(int status)780Sstevel@tonic-gate monitord_exit(int status)
790Sstevel@tonic-gate {
800Sstevel@tonic-gate 	monitord_print(1, gettext("exit status = %d\n"), status);
810Sstevel@tonic-gate 
820Sstevel@tonic-gate 	monitord_print(8, "hold_daemon_lock %d\n", hold_daemon_lock);
830Sstevel@tonic-gate 	if (hold_daemon_lock) {
840Sstevel@tonic-gate 		exit_daemon_lock();
850Sstevel@tonic-gate 	}
860Sstevel@tonic-gate 	md_exit(sp, status);
870Sstevel@tonic-gate }
880Sstevel@tonic-gate 
890Sstevel@tonic-gate 
900Sstevel@tonic-gate /*
910Sstevel@tonic-gate  * When SIGHUP is received, reload modules?
920Sstevel@tonic-gate  */
930Sstevel@tonic-gate void
catch_sig(int sig)940Sstevel@tonic-gate catch_sig(int sig)
950Sstevel@tonic-gate {
960Sstevel@tonic-gate 	boolean_e startup = False;
970Sstevel@tonic-gate 	md_error_t status = mdnullerror;
980Sstevel@tonic-gate 	boolean_e sig_verbose = True;
990Sstevel@tonic-gate 
1000Sstevel@tonic-gate 	if (sig == SIGALRM) {
1010Sstevel@tonic-gate 		monitord_print(6, gettext("SIGALRM processing"));
1020Sstevel@tonic-gate 		if (probe_started == True) {
1030Sstevel@tonic-gate 			monitord_print(6, gettext(
1040Sstevel@tonic-gate 			    " probe_started returning\n"));
1050Sstevel@tonic-gate 			return;
1060Sstevel@tonic-gate 		}
1070Sstevel@tonic-gate 		monitord_print(6, gettext(
1080Sstevel@tonic-gate 		    " starting probe from signal handler\n"));
1090Sstevel@tonic-gate 		probe_all_devs(startup, &status, sig_verbose);
110*11053SSurya.Prakki@Sun.COM 		(void) setitimer(ITIMER_REAL, &itimer, NULL);
1110Sstevel@tonic-gate 	}
1120Sstevel@tonic-gate 	if (sig == SIGHUP)
1130Sstevel@tonic-gate 		monitord_exit(sig);
1140Sstevel@tonic-gate }
1150Sstevel@tonic-gate 
1160Sstevel@tonic-gate /*
1170Sstevel@tonic-gate  * Use an advisory lock to ensure that only one daemon process is
1180Sstevel@tonic-gate  * active at any point in time.
1190Sstevel@tonic-gate  */
1200Sstevel@tonic-gate static pid_t
check_daemon_lock(void)1210Sstevel@tonic-gate check_daemon_lock(void)
1220Sstevel@tonic-gate {
1230Sstevel@tonic-gate 	struct flock	lock;
1240Sstevel@tonic-gate 
1250Sstevel@tonic-gate 	monitord_print(1, gettext("check_daemon_lock: lock file = %s\n"),
1260Sstevel@tonic-gate 	    daemon_lock_file);
1270Sstevel@tonic-gate 
1280Sstevel@tonic-gate 	daemon_lock_fd = open(daemon_lock_file, O_CREAT|O_RDWR, 0644);
1290Sstevel@tonic-gate 	if (daemon_lock_fd < 0) {
1300Sstevel@tonic-gate 		monitord_print(0, "open(%s) - %s\n", daemon_lock_file,
1310Sstevel@tonic-gate 		    strerror(errno));
1320Sstevel@tonic-gate 		monitord_exit(-1);
1330Sstevel@tonic-gate 	}
1340Sstevel@tonic-gate 
1350Sstevel@tonic-gate 	lock.l_type = F_WRLCK;
1360Sstevel@tonic-gate 	lock.l_whence = SEEK_SET;
1370Sstevel@tonic-gate 	lock.l_start = 0;
1380Sstevel@tonic-gate 	lock.l_len = 0;
1390Sstevel@tonic-gate 
1400Sstevel@tonic-gate 	if (fcntl(daemon_lock_fd, F_GETLK, &lock) == -1) {
1410Sstevel@tonic-gate 		monitord_print(0, "lock(%s) - %s", daemon_lock_file,
1420Sstevel@tonic-gate 		    strerror(errno));
1430Sstevel@tonic-gate 		monitord_exit(-1);
1440Sstevel@tonic-gate 	}
1450Sstevel@tonic-gate 
1460Sstevel@tonic-gate 	return (lock.l_type == F_UNLCK ? 0 : lock.l_pid);
1470Sstevel@tonic-gate }
1480Sstevel@tonic-gate 
1490Sstevel@tonic-gate static pid_t
enter_daemon_lock(void)1500Sstevel@tonic-gate enter_daemon_lock(void)
1510Sstevel@tonic-gate {
1520Sstevel@tonic-gate 	struct flock	lock;
1530Sstevel@tonic-gate 
1540Sstevel@tonic-gate 	monitord_print(1, gettext(
1550Sstevel@tonic-gate 	    "enter_daemon_lock: lock file = %s\n"), daemon_lock_file);
1560Sstevel@tonic-gate 
1570Sstevel@tonic-gate 	daemon_lock_fd = open(daemon_lock_file, O_CREAT|O_RDWR, 0644);
1580Sstevel@tonic-gate 	if (daemon_lock_fd < 0) {
1590Sstevel@tonic-gate 		monitord_print(0, "open(%s) - %s\n",
1600Sstevel@tonic-gate 		    daemon_lock_file, strerror(errno));
1610Sstevel@tonic-gate 		monitord_exit(-1);
1620Sstevel@tonic-gate 	}
1630Sstevel@tonic-gate 
1640Sstevel@tonic-gate 	lock.l_type = F_WRLCK;
1650Sstevel@tonic-gate 	lock.l_whence = SEEK_SET;
1660Sstevel@tonic-gate 	lock.l_start = 0;
1670Sstevel@tonic-gate 	lock.l_len = 0;
1680Sstevel@tonic-gate 
1690Sstevel@tonic-gate 	if (fcntl(daemon_lock_fd, F_SETLK, &lock) == -1) {
1700Sstevel@tonic-gate 
1710Sstevel@tonic-gate 		if (errno == EAGAIN || errno == EDEADLK) {
1720Sstevel@tonic-gate 
1730Sstevel@tonic-gate 			if (fcntl(daemon_lock_fd, F_GETLK, &lock) == -1) {
1740Sstevel@tonic-gate 				monitord_print(0, "lock(%s) - %s",
1750Sstevel@tonic-gate 				    daemon_lock_file, strerror(errno));
1760Sstevel@tonic-gate 				monitord_exit(-1);
1770Sstevel@tonic-gate 			}
1780Sstevel@tonic-gate 
1790Sstevel@tonic-gate 			return (lock.l_pid);
1800Sstevel@tonic-gate 		}
1810Sstevel@tonic-gate 	}
1820Sstevel@tonic-gate 	hold_daemon_lock = 1;
1830Sstevel@tonic-gate 
1840Sstevel@tonic-gate 	return (0);
1850Sstevel@tonic-gate }
1860Sstevel@tonic-gate 
1870Sstevel@tonic-gate /*
1880Sstevel@tonic-gate  * Drop the advisory daemon lock, close lock file
1890Sstevel@tonic-gate  */
1900Sstevel@tonic-gate static void
exit_daemon_lock(void)1910Sstevel@tonic-gate exit_daemon_lock(void)
1920Sstevel@tonic-gate {
1930Sstevel@tonic-gate 	struct flock lock;
1940Sstevel@tonic-gate 
1950Sstevel@tonic-gate 	lock.l_type = F_UNLCK;
1960Sstevel@tonic-gate 	lock.l_whence = SEEK_SET;
1970Sstevel@tonic-gate 	lock.l_start = 0;
1980Sstevel@tonic-gate 	lock.l_len = 0;
1990Sstevel@tonic-gate 
2000Sstevel@tonic-gate 	if (fcntl(daemon_lock_fd, F_SETLK, &lock) == -1) {
2010Sstevel@tonic-gate 		monitord_print(0, "unlock(%s) - %s",
2020Sstevel@tonic-gate 		    daemon_lock_file, strerror(errno));
2030Sstevel@tonic-gate 	}
2040Sstevel@tonic-gate 
2050Sstevel@tonic-gate 	if (close(daemon_lock_fd) == -1) {
2060Sstevel@tonic-gate 		monitord_print(0, "close(%s) failed - %s\n",
2070Sstevel@tonic-gate 		    daemon_lock_file, strerror(errno));
2080Sstevel@tonic-gate 		monitord_exit(-1);
2090Sstevel@tonic-gate 	}
210*11053SSurya.Prakki@Sun.COM 	(void) unlink(daemon_lock_file);
2110Sstevel@tonic-gate }
2120Sstevel@tonic-gate 
2130Sstevel@tonic-gate 
2140Sstevel@tonic-gate /*
2150Sstevel@tonic-gate  * print error messages to the terminal or to syslog
2160Sstevel@tonic-gate  */
2170Sstevel@tonic-gate /*PRINTFLIKE2*/
2180Sstevel@tonic-gate void
monitord_print(int level,char * message,...)2190Sstevel@tonic-gate monitord_print(int level, char *message, ...)
2200Sstevel@tonic-gate {
2210Sstevel@tonic-gate 	va_list ap;
2220Sstevel@tonic-gate 	static int newline = 1;
2230Sstevel@tonic-gate 
2240Sstevel@tonic-gate 	if (level > debug_level) {
2250Sstevel@tonic-gate 		return;
2260Sstevel@tonic-gate 	}
2270Sstevel@tonic-gate 
2280Sstevel@tonic-gate 	va_start(ap, message);
2290Sstevel@tonic-gate 	if (level == 0) {
2300Sstevel@tonic-gate 		if (logflag) {
2310Sstevel@tonic-gate 			(void) vsyslog(LOG_ERR, message, ap);
2320Sstevel@tonic-gate 		} else {
2330Sstevel@tonic-gate 			(void) vfprintf(stderr, message, ap);
2340Sstevel@tonic-gate 		}
2350Sstevel@tonic-gate 
2360Sstevel@tonic-gate 	} else {
2370Sstevel@tonic-gate 		if (logflag) {
2380Sstevel@tonic-gate 			(void) syslog(LOG_DEBUG, "%s[%ld]: ",
239*11053SSurya.Prakki@Sun.COM 			    prog, getpid());
2400Sstevel@tonic-gate 			(void) vsyslog(LOG_DEBUG, message, ap);
2410Sstevel@tonic-gate 		} else {
2420Sstevel@tonic-gate 			if (newline) {
2430Sstevel@tonic-gate 				(void) fprintf(stdout, "%s[%ld]: ",
244*11053SSurya.Prakki@Sun.COM 				    prog, getpid());
2450Sstevel@tonic-gate 				(void) vfprintf(stdout, message, ap);
2460Sstevel@tonic-gate 			} else {
2470Sstevel@tonic-gate 				(void) vfprintf(stdout, message, ap);
2480Sstevel@tonic-gate 			}
2490Sstevel@tonic-gate 		}
2500Sstevel@tonic-gate 	}
2510Sstevel@tonic-gate 	if (message[strlen(message)-1] == '\n') {
2520Sstevel@tonic-gate 		newline = 1;
2530Sstevel@tonic-gate 	} else {
2540Sstevel@tonic-gate 		newline = 0;
2550Sstevel@tonic-gate 	}
2560Sstevel@tonic-gate 	va_end(ap);
2570Sstevel@tonic-gate }
2580Sstevel@tonic-gate 
2590Sstevel@tonic-gate 
2600Sstevel@tonic-gate char *
int2string(intmap_t * map,int value)2610Sstevel@tonic-gate int2string(intmap_t *map, int value)
2620Sstevel@tonic-gate {
2630Sstevel@tonic-gate 	const char	*name = (const char *)NULL;
2640Sstevel@tonic-gate 	char		charstr[100];
2650Sstevel@tonic-gate 
2660Sstevel@tonic-gate 	for (; map->im_name != (const char *)NULL; map++) {
2670Sstevel@tonic-gate 		if (map->im_int == value) {
2680Sstevel@tonic-gate 			name = map->im_name;
2690Sstevel@tonic-gate 			break;
2700Sstevel@tonic-gate 		}
2710Sstevel@tonic-gate 	}
2720Sstevel@tonic-gate 	if (name == (const char *)NULL) {
2730Sstevel@tonic-gate 		/* No match.  Convert the string to an int. */
2740Sstevel@tonic-gate 		(void) sprintf(charstr, "%d", value);
2750Sstevel@tonic-gate 	} else {
2760Sstevel@tonic-gate 		(void) snprintf(charstr, sizeof (charstr), "%d %s",
2770Sstevel@tonic-gate 		    value, name);
2780Sstevel@tonic-gate 	}
2790Sstevel@tonic-gate 	return (strdup(charstr));
2800Sstevel@tonic-gate }
2810Sstevel@tonic-gate 
2820Sstevel@tonic-gate void
probe_all_devs(boolean_e startup,md_error_t * statusp,boolean_e verbose)2830Sstevel@tonic-gate probe_all_devs(boolean_e startup, md_error_t *statusp, boolean_e verbose)
2840Sstevel@tonic-gate {
2850Sstevel@tonic-gate 	set_t		max_sets, set_idx;
2860Sstevel@tonic-gate 
2870Sstevel@tonic-gate 	probe_started = True;
288*11053SSurya.Prakki@Sun.COM 	(void) set_snarf(statusp);
2890Sstevel@tonic-gate 
2900Sstevel@tonic-gate 	if ((max_sets = get_max_sets(statusp)) == 0) {
2910Sstevel@tonic-gate 		mde_perror(statusp, gettext(
2920Sstevel@tonic-gate 		    "Can't find max number of sets\n"));
2930Sstevel@tonic-gate 		monitord_exit(1);
2940Sstevel@tonic-gate 	}
2950Sstevel@tonic-gate 
2960Sstevel@tonic-gate 	/*
2970Sstevel@tonic-gate 	 * We delete the FF_Q to avoid recurse errors. Yes we will lose
2980Sstevel@tonic-gate 	 * some but its the corner case.
2990Sstevel@tonic-gate 	 */
3000Sstevel@tonic-gate 
3010Sstevel@tonic-gate 	if (startup == False &&
3020Sstevel@tonic-gate 	    (meta_notify_deleteq(MD_FF_Q, statusp) != 0)) {
3030Sstevel@tonic-gate 		mde_perror(statusp, gettext(
3040Sstevel@tonic-gate 		    "delete queue failed\n"));
3050Sstevel@tonic-gate 		monitord_exit(1);
3060Sstevel@tonic-gate 	}
3070Sstevel@tonic-gate 
3080Sstevel@tonic-gate 	for (set_idx = 0; set_idx < max_sets; set_idx++) {
3090Sstevel@tonic-gate 		if ((sp = metasetnosetname(set_idx, statusp)) == NULL) {
3100Sstevel@tonic-gate 			if (mdiserror(statusp, MDE_NO_SET) == 0) {
3110Sstevel@tonic-gate 				/*
3120Sstevel@tonic-gate 				 * done break the loop
3130Sstevel@tonic-gate 				 */
3140Sstevel@tonic-gate 				break;
3150Sstevel@tonic-gate 			} else {
3160Sstevel@tonic-gate 				mdclrerror(statusp);
3170Sstevel@tonic-gate 				continue;
3180Sstevel@tonic-gate 			}
3190Sstevel@tonic-gate 		}
3200Sstevel@tonic-gate 
3210Sstevel@tonic-gate 		/* if we dont have ownership or cannot lock it continue. */
3220Sstevel@tonic-gate 		if ((meta_check_ownership(sp, statusp) == NULL) &&
323*11053SSurya.Prakki@Sun.COM 		    meta_lock(sp, TRUE, statusp))
3240Sstevel@tonic-gate 			continue;
3250Sstevel@tonic-gate 
3260Sstevel@tonic-gate 		/* Skip if a MN set */
3270Sstevel@tonic-gate 		if (meta_is_mn_set(sp, statusp)) {
328*11053SSurya.Prakki@Sun.COM 			(void) meta_unlock(sp, statusp);
3290Sstevel@tonic-gate 			continue;
3300Sstevel@tonic-gate 		}
3310Sstevel@tonic-gate 
3320Sstevel@tonic-gate 		probe_mirror_devs(verbose);
3330Sstevel@tonic-gate 		probe_raid_devs(verbose);
3340Sstevel@tonic-gate 		probe_trans_devs(verbose);
3350Sstevel@tonic-gate 		probe_hotspare_devs(verbose);
336*11053SSurya.Prakki@Sun.COM 		(void) meta_unlock(sp, statusp);
3370Sstevel@tonic-gate 	}
3380Sstevel@tonic-gate 	if (meta_notify_createq(MD_FF_Q, 0, statusp)) {
3390Sstevel@tonic-gate 		mde_perror(statusp, gettext(
3400Sstevel@tonic-gate 		    "create queue failed"));
3410Sstevel@tonic-gate 		monitord_exit(1);
3420Sstevel@tonic-gate 	}
3430Sstevel@tonic-gate 	probe_started = False;
3440Sstevel@tonic-gate 	/*
3450Sstevel@tonic-gate 	 * need to do it here only at startup.
3460Sstevel@tonic-gate 	 * The daemon will restart the alarm.
3470Sstevel@tonic-gate 	 */
3480Sstevel@tonic-gate 
3490Sstevel@tonic-gate 	if (startup == True)
350*11053SSurya.Prakki@Sun.COM 		(void) setitimer(ITIMER_REAL, &itimer, NULL);
3510Sstevel@tonic-gate }
3520Sstevel@tonic-gate 
3530Sstevel@tonic-gate evid_t
wait_for_event(md_error_t * statusp)3540Sstevel@tonic-gate wait_for_event(md_error_t *statusp)
3550Sstevel@tonic-gate {
3560Sstevel@tonic-gate 	md_ev_t		event;
3570Sstevel@tonic-gate 
3580Sstevel@tonic-gate 
3590Sstevel@tonic-gate 	event.setno = EV_ALLSETS;
3600Sstevel@tonic-gate 	event.obj = EV_ALLOBJS;
3610Sstevel@tonic-gate 
3620Sstevel@tonic-gate 	do {
3630Sstevel@tonic-gate 		if (meta_notify_getev(MD_FF_Q, EVFLG_WAIT, &event,
364*11053SSurya.Prakki@Sun.COM 		    statusp) < 0) {
3650Sstevel@tonic-gate 			monitord_print(8,
3660Sstevel@tonic-gate 			    "meta_notify_getev: errno 0x%x\n", -errno);
3670Sstevel@tonic-gate 			monitord_exit(-errno);
3680Sstevel@tonic-gate 		}
3690Sstevel@tonic-gate 	} while ((event.ev != EV_IOERR && event.ev != EV_ERRED &&
370*11053SSurya.Prakki@Sun.COM 	    event.ev != EV_LASTERRED));
3710Sstevel@tonic-gate 	return (event.ev);
3720Sstevel@tonic-gate }
3730Sstevel@tonic-gate 
37462Sjeanm int
main(int argc,char ** argv)3750Sstevel@tonic-gate main(int argc, char **argv)
3760Sstevel@tonic-gate {
3770Sstevel@tonic-gate 	boolean_e	startup = True;
3780Sstevel@tonic-gate 	boolean_e	verbose = False;
3790Sstevel@tonic-gate 	int		i;
3800Sstevel@tonic-gate 	char		c;
3810Sstevel@tonic-gate 	md_error_t	status = mdnullerror;
3820Sstevel@tonic-gate 	struct sigaction act;
3830Sstevel@tonic-gate 	sigset_t	mask;
3840Sstevel@tonic-gate 	unsigned long	timerval = 0;
3850Sstevel@tonic-gate 
3860Sstevel@tonic-gate 	/*
3870Sstevel@tonic-gate 	 * Get the locale set up before calling any other routines
3880Sstevel@tonic-gate 	 * with messages to ouput.  Just in case we're not in a build
3890Sstevel@tonic-gate 	 * environment, make sure that TEXT_DOMAIN gets set to
3900Sstevel@tonic-gate 	 * something.
3910Sstevel@tonic-gate 	 */
3920Sstevel@tonic-gate #if !defined(TEXT_DOMAIN)
3930Sstevel@tonic-gate #define	TEXT_DOMAIN "SYS_TEST"
3940Sstevel@tonic-gate #endif
3950Sstevel@tonic-gate 	(void) setlocale(LC_ALL, "");
3960Sstevel@tonic-gate 	(void) textdomain(TEXT_DOMAIN);
3970Sstevel@tonic-gate 
3980Sstevel@tonic-gate 	if (sdssc_bind_library() == SDSSC_ERROR) {
3990Sstevel@tonic-gate 		(void) printf(gettext(
4000Sstevel@tonic-gate 		    "%s: Interface error with libsds_sc.so\n"), argv[0]);
4010Sstevel@tonic-gate 		exit(1);
4020Sstevel@tonic-gate 	}
4030Sstevel@tonic-gate 
4040Sstevel@tonic-gate 	if (md_init(argc, argv, 0, 1, &status) != 0 ||
405*11053SSurya.Prakki@Sun.COM 	    meta_check_root(&status) != 0) {
4060Sstevel@tonic-gate 		mde_perror(&status, "");
4070Sstevel@tonic-gate 		monitord_exit(1);
4080Sstevel@tonic-gate 	}
4090Sstevel@tonic-gate 
4100Sstevel@tonic-gate 	(void) sigfillset(&mask);
411*11053SSurya.Prakki@Sun.COM 	(void) thr_sigsetmask(SIG_BLOCK, &mask, NULL);
4120Sstevel@tonic-gate 
4130Sstevel@tonic-gate 	if (argc > 7) {
4140Sstevel@tonic-gate 		usage();
4150Sstevel@tonic-gate 	}
4160Sstevel@tonic-gate 
4170Sstevel@tonic-gate 	if ((prog = strrchr(argv[0], '/')) == NULL) {
4180Sstevel@tonic-gate 		prog = argv[0];
4190Sstevel@tonic-gate 	} else {
4200Sstevel@tonic-gate 		prog++;
4210Sstevel@tonic-gate 	}
4220Sstevel@tonic-gate 
4230Sstevel@tonic-gate 	/*
4240Sstevel@tonic-gate 	 * Reset optind/opterr so that the command line arguments can be
4250Sstevel@tonic-gate 	 * parsed. This is in case anything has already called getopt,
4260Sstevel@tonic-gate 	 * for example sdssc_cmd_proxy which is not currently used but
4270Sstevel@tonic-gate 	 * may be in the future.
4280Sstevel@tonic-gate 	 */
4290Sstevel@tonic-gate 	optind = 1;
4300Sstevel@tonic-gate 	opterr = 1;
4310Sstevel@tonic-gate 	while ((c = getopt(argc, argv, "ivd:t:")) != EOF) {
4320Sstevel@tonic-gate 		switch (c) {
4330Sstevel@tonic-gate 		case 'v':
4340Sstevel@tonic-gate 			verbose = True;
4350Sstevel@tonic-gate 			break;
4360Sstevel@tonic-gate 		case 'i':
4370Sstevel@tonic-gate 			issue_ioctl = True;
4380Sstevel@tonic-gate 			break;
4390Sstevel@tonic-gate 		case 'd':
4400Sstevel@tonic-gate 			debug_level = atoi(optarg);
4410Sstevel@tonic-gate 			break;
4420Sstevel@tonic-gate 		case 't':
4430Sstevel@tonic-gate 			timerval = atol(optarg);
4440Sstevel@tonic-gate 			break;
4450Sstevel@tonic-gate 		default:
4460Sstevel@tonic-gate 			usage();
4470Sstevel@tonic-gate 			exit(0);
4480Sstevel@tonic-gate 		}
4490Sstevel@tonic-gate 	}
4500Sstevel@tonic-gate 
4510Sstevel@tonic-gate 	if (timerval == 0) {
4520Sstevel@tonic-gate 		monitord_print(8, gettext(
4530Sstevel@tonic-gate 		    "operating in interrupt mode\n"));
4540Sstevel@tonic-gate 	} else {
4550Sstevel@tonic-gate 		itimer.it_value.tv_sec = timerval;
4560Sstevel@tonic-gate 		itimer.it_interval.tv_sec = timerval;
4570Sstevel@tonic-gate 		monitord_print(8, gettext(
4580Sstevel@tonic-gate 		    "set value and interval %lu sec  mode\n"), timerval);
4590Sstevel@tonic-gate 	}
4600Sstevel@tonic-gate 	/*
4610Sstevel@tonic-gate 	 * set up our signal handler for SIGALRM. The
4620Sstevel@tonic-gate 	 * rest are setup by md_init.
4630Sstevel@tonic-gate 	 */
4640Sstevel@tonic-gate 
4650Sstevel@tonic-gate 	act.sa_handler = catch_sig;
4660Sstevel@tonic-gate 	(void) sigemptyset(&act.sa_mask);
4670Sstevel@tonic-gate 	act.sa_flags = SA_RESTART;
4680Sstevel@tonic-gate 	(void) sigaction(SIGALRM, &act, NULL);
4690Sstevel@tonic-gate 	(void) sigaction(SIGHUP, &act, NULL);
4700Sstevel@tonic-gate 
4710Sstevel@tonic-gate 	(void) sigemptyset(&mask);
4720Sstevel@tonic-gate 	(void) sigaddset(&mask, SIGALRM);
4730Sstevel@tonic-gate 	(void) sigaddset(&mask, SIGHUP);
474*11053SSurya.Prakki@Sun.COM 	(void) thr_sigsetmask(SIG_UNBLOCK, &mask, NULL);
4750Sstevel@tonic-gate 
4760Sstevel@tonic-gate 	/* demonize ourselves */
4770Sstevel@tonic-gate 	if (debug_level < DEBUG_LEVEL_FORK) {
4780Sstevel@tonic-gate 		pid_t pid;
4790Sstevel@tonic-gate 
4800Sstevel@tonic-gate 		if ((pid = check_daemon_lock()) != 0) {
4810Sstevel@tonic-gate 			monitord_print(0, gettext(
4820Sstevel@tonic-gate 			    "mdmonitord daemon pid %ld already running\n"),
4830Sstevel@tonic-gate 			    pid);
4840Sstevel@tonic-gate 			exit(-1);
4850Sstevel@tonic-gate 		}
4860Sstevel@tonic-gate 
4870Sstevel@tonic-gate 		if (fork()) {
4880Sstevel@tonic-gate 			exit(0);
4890Sstevel@tonic-gate 		}
4900Sstevel@tonic-gate 
4910Sstevel@tonic-gate 		/* only one daemon can run at a time */
4920Sstevel@tonic-gate 		if ((pid = enter_daemon_lock()) != 0) {
4930Sstevel@tonic-gate 			monitord_print(0, gettext(
4940Sstevel@tonic-gate 			    "mdmonitord daemon pid %ld already running\n"),
4950Sstevel@tonic-gate 			    pid);
4960Sstevel@tonic-gate 			exit(-1);
4970Sstevel@tonic-gate 		}
4980Sstevel@tonic-gate 
4990Sstevel@tonic-gate 		(void) chdir("/");
5000Sstevel@tonic-gate 
5010Sstevel@tonic-gate 		(void) setsid();
5020Sstevel@tonic-gate 		if (debug_level <= 1) {
5030Sstevel@tonic-gate 			for (i = 0; i < 3; i++) {
5040Sstevel@tonic-gate 				(void) close(i);
5050Sstevel@tonic-gate 			}
5060Sstevel@tonic-gate 			(void) open("/dev/null", 0);
5070Sstevel@tonic-gate 			(void) dup2(0, 1);
5080Sstevel@tonic-gate 			(void) dup2(0, 2);
5090Sstevel@tonic-gate 			logflag = 1;
5100Sstevel@tonic-gate 		}
5110Sstevel@tonic-gate 	}
5120Sstevel@tonic-gate 
5130Sstevel@tonic-gate 	openlog("mdmonitord", LOG_PID, LOG_DAEMON);
5140Sstevel@tonic-gate 
5150Sstevel@tonic-gate 	monitord_print(8, gettext(
5160Sstevel@tonic-gate 	    "mdmonitord started, debug level = %d\n"), debug_level);
5170Sstevel@tonic-gate 
5180Sstevel@tonic-gate 
5190Sstevel@tonic-gate 	/* loop forever waiting for events */
5200Sstevel@tonic-gate 	do {
5210Sstevel@tonic-gate 		metaflushnames(1);
5220Sstevel@tonic-gate 		probe_all_devs(startup, &status, verbose);
5230Sstevel@tonic-gate 		startup = False; /* since we have gone through once */
5240Sstevel@tonic-gate 	} while (wait_for_event(&status));
52562Sjeanm 	return (0);
5260Sstevel@tonic-gate }
527