17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 52a9459bdSsangeeta * Common Development and Distribution License (the "License"). 62a9459bdSsangeeta * You may not use this file except in compliance with the License. 77c478bd9Sstevel@tonic-gate * 87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 117c478bd9Sstevel@tonic-gate * and limitations under the License. 127c478bd9Sstevel@tonic-gate * 137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 187c478bd9Sstevel@tonic-gate * 197c478bd9Sstevel@tonic-gate * CDDL HEADER END 207c478bd9Sstevel@tonic-gate */ 21*98573c19SMarcel Telka 22*98573c19SMarcel Telka /* 23*98573c19SMarcel Telka * Copyright 2015 Nexenta Systems, Inc. All rights reserved. 24*98573c19SMarcel Telka */ 25*98573c19SMarcel Telka 267c478bd9Sstevel@tonic-gate /* 272a9459bdSsangeeta * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 287c478bd9Sstevel@tonic-gate * Use is subject to license terms. 297c478bd9Sstevel@tonic-gate */ 307c478bd9Sstevel@tonic-gate 317c478bd9Sstevel@tonic-gate /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 327c478bd9Sstevel@tonic-gate /* All Rights Reserved */ 337c478bd9Sstevel@tonic-gate 347c478bd9Sstevel@tonic-gate /* 357c478bd9Sstevel@tonic-gate * University Copyright- Copyright (c) 1982, 1986, 1988 367c478bd9Sstevel@tonic-gate * The Regents of the University of California 377c478bd9Sstevel@tonic-gate * All Rights Reserved 387c478bd9Sstevel@tonic-gate * 397c478bd9Sstevel@tonic-gate * University Acknowledgment- Portions of this document are derived from 407c478bd9Sstevel@tonic-gate * software developed by the University of California, Berkeley, and its 417c478bd9Sstevel@tonic-gate * contributors. 427c478bd9Sstevel@tonic-gate */ 437c478bd9Sstevel@tonic-gate 44bbaa8b60SDan Kruchinin /* 45bbaa8b60SDan Kruchinin * Copyright (c) 2012 by Delphix. All rights reserved. 46bbaa8b60SDan Kruchinin */ 477c478bd9Sstevel@tonic-gate 487c478bd9Sstevel@tonic-gate /* 497c478bd9Sstevel@tonic-gate * sm_statd.c consists of routines used for the intermediate 507c478bd9Sstevel@tonic-gate * statd implementation(3.2 rpc.statd); 517c478bd9Sstevel@tonic-gate * it creates an entry in "current" directory for each site that it monitors; 527c478bd9Sstevel@tonic-gate * after crash and recovery, it moves all entries in "current" 537c478bd9Sstevel@tonic-gate * to "backup" directory, and notifies the corresponding statd of its recovery. 547c478bd9Sstevel@tonic-gate */ 557c478bd9Sstevel@tonic-gate 567c478bd9Sstevel@tonic-gate #include <stdio.h> 577c478bd9Sstevel@tonic-gate #include <stdlib.h> 587c478bd9Sstevel@tonic-gate #include <unistd.h> 597c478bd9Sstevel@tonic-gate #include <string.h> 607c478bd9Sstevel@tonic-gate #include <syslog.h> 617c478bd9Sstevel@tonic-gate #include <netdb.h> 627c478bd9Sstevel@tonic-gate #include <sys/types.h> 637c478bd9Sstevel@tonic-gate #include <sys/stat.h> 647c478bd9Sstevel@tonic-gate #include <sys/file.h> 657c478bd9Sstevel@tonic-gate #include <sys/param.h> 667c478bd9Sstevel@tonic-gate #include <arpa/inet.h> 677c478bd9Sstevel@tonic-gate #include <dirent.h> 687c478bd9Sstevel@tonic-gate #include <rpc/rpc.h> 697c478bd9Sstevel@tonic-gate #include <rpcsvc/sm_inter.h> 707c478bd9Sstevel@tonic-gate #include <rpcsvc/nsm_addr.h> 717c478bd9Sstevel@tonic-gate #include <errno.h> 727c478bd9Sstevel@tonic-gate #include <memory.h> 737c478bd9Sstevel@tonic-gate #include <signal.h> 747c478bd9Sstevel@tonic-gate #include <synch.h> 757c478bd9Sstevel@tonic-gate #include <thread.h> 767c478bd9Sstevel@tonic-gate #include <limits.h> 777c478bd9Sstevel@tonic-gate #include <strings.h> 787c478bd9Sstevel@tonic-gate #include "sm_statd.h" 797c478bd9Sstevel@tonic-gate 807c478bd9Sstevel@tonic-gate 817c478bd9Sstevel@tonic-gate int LOCAL_STATE; 827c478bd9Sstevel@tonic-gate 837c478bd9Sstevel@tonic-gate sm_hash_t mon_table[MAX_HASHSIZE]; 847c478bd9Sstevel@tonic-gate static sm_hash_t record_table[MAX_HASHSIZE]; 857c478bd9Sstevel@tonic-gate static sm_hash_t recov_q; 867c478bd9Sstevel@tonic-gate 877c478bd9Sstevel@tonic-gate static name_entry *find_name(name_entry **namepp, char *name); 887c478bd9Sstevel@tonic-gate static name_entry *insert_name(name_entry **namepp, char *name, 897c478bd9Sstevel@tonic-gate int need_alloc); 907c478bd9Sstevel@tonic-gate static void delete_name(name_entry **namepp, char *name); 917c478bd9Sstevel@tonic-gate static void remove_name(char *name, int op, int startup); 927c478bd9Sstevel@tonic-gate static int statd_call_statd(char *name); 937c478bd9Sstevel@tonic-gate static void pr_name(char *name, int flag); 94*98573c19SMarcel Telka static void *thr_statd_init(void); 95*98573c19SMarcel Telka static void *sm_try(void); 967c478bd9Sstevel@tonic-gate static void *thr_call_statd(void *); 977c478bd9Sstevel@tonic-gate static void remove_single_name(char *name, char *dir1, char *dir2); 987c478bd9Sstevel@tonic-gate static int move_file(char *fromdir, char *file, char *todir); 997c478bd9Sstevel@tonic-gate static int count_symlinks(char *dir, char *name, int *count); 1007c478bd9Sstevel@tonic-gate static char *family2string(sa_family_t family); 1017c478bd9Sstevel@tonic-gate 1027c478bd9Sstevel@tonic-gate /* 1037c478bd9Sstevel@tonic-gate * called when statd first comes up; it searches /etc/sm to gather 1047c478bd9Sstevel@tonic-gate * all entries to notify its own failure 1057c478bd9Sstevel@tonic-gate */ 1067c478bd9Sstevel@tonic-gate void 107*98573c19SMarcel Telka statd_init(void) 1087c478bd9Sstevel@tonic-gate { 1094bc0a2efScasper struct dirent *dirp; 1107c478bd9Sstevel@tonic-gate DIR *dp; 1117c478bd9Sstevel@tonic-gate FILE *fp, *fp_tmp; 1127c478bd9Sstevel@tonic-gate int i, tmp_state; 1137c478bd9Sstevel@tonic-gate char state_file[MAXPATHLEN+SM_MAXPATHLEN]; 1147c478bd9Sstevel@tonic-gate 1157c478bd9Sstevel@tonic-gate if (debug) 1167c478bd9Sstevel@tonic-gate (void) printf("enter statd_init\n"); 1177c478bd9Sstevel@tonic-gate 1187c478bd9Sstevel@tonic-gate /* 1197c478bd9Sstevel@tonic-gate * First try to open the file. If that fails, try to create it. 1207c478bd9Sstevel@tonic-gate * If that fails, give up. 1217c478bd9Sstevel@tonic-gate */ 122*98573c19SMarcel Telka if ((fp = fopen(STATE, "r+")) == NULL) { 123*98573c19SMarcel Telka if ((fp = fopen(STATE, "w+")) == NULL) { 1247c478bd9Sstevel@tonic-gate syslog(LOG_ERR, "can't open %s: %m", STATE); 1257c478bd9Sstevel@tonic-gate exit(1); 1267c478bd9Sstevel@tonic-gate } else 1277c478bd9Sstevel@tonic-gate (void) chmod(STATE, 0644); 128*98573c19SMarcel Telka } 1297c478bd9Sstevel@tonic-gate if ((fscanf(fp, "%d", &LOCAL_STATE)) == EOF) { 1307c478bd9Sstevel@tonic-gate if (debug >= 2) 1317c478bd9Sstevel@tonic-gate (void) printf("empty file\n"); 1327c478bd9Sstevel@tonic-gate LOCAL_STATE = 0; 1337c478bd9Sstevel@tonic-gate } 1347c478bd9Sstevel@tonic-gate 1357c478bd9Sstevel@tonic-gate /* 1367c478bd9Sstevel@tonic-gate * Scan alternate paths for largest "state" number 1377c478bd9Sstevel@tonic-gate */ 1387c478bd9Sstevel@tonic-gate for (i = 0; i < pathix; i++) { 1397c478bd9Sstevel@tonic-gate (void) sprintf(state_file, "%s/statmon/state", path_name[i]); 140*98573c19SMarcel Telka if ((fp_tmp = fopen(state_file, "r+")) == NULL) { 141*98573c19SMarcel Telka if ((fp_tmp = fopen(state_file, "w+")) == NULL) { 1427c478bd9Sstevel@tonic-gate if (debug) 1437c478bd9Sstevel@tonic-gate syslog(LOG_ERR, 1447c478bd9Sstevel@tonic-gate "can't open %s: %m", 1457c478bd9Sstevel@tonic-gate state_file); 1467c478bd9Sstevel@tonic-gate continue; 1477c478bd9Sstevel@tonic-gate } else 1487c478bd9Sstevel@tonic-gate (void) chmod(state_file, 0644); 1497c478bd9Sstevel@tonic-gate } 1507c478bd9Sstevel@tonic-gate if ((fscanf(fp_tmp, "%d", &tmp_state)) == EOF) { 1517c478bd9Sstevel@tonic-gate if (debug) 1527c478bd9Sstevel@tonic-gate syslog(LOG_ERR, 1537c478bd9Sstevel@tonic-gate "statd: %s: file empty\n", state_file); 1547c478bd9Sstevel@tonic-gate (void) fclose(fp_tmp); 1557c478bd9Sstevel@tonic-gate continue; 1567c478bd9Sstevel@tonic-gate } 1577c478bd9Sstevel@tonic-gate if (tmp_state > LOCAL_STATE) { 1587c478bd9Sstevel@tonic-gate LOCAL_STATE = tmp_state; 1597c478bd9Sstevel@tonic-gate if (debug) 1607c478bd9Sstevel@tonic-gate (void) printf("Update LOCAL STATE: %d\n", 1617c478bd9Sstevel@tonic-gate tmp_state); 1627c478bd9Sstevel@tonic-gate } 1637c478bd9Sstevel@tonic-gate (void) fclose(fp_tmp); 1647c478bd9Sstevel@tonic-gate } 1657c478bd9Sstevel@tonic-gate 1667c478bd9Sstevel@tonic-gate LOCAL_STATE = ((LOCAL_STATE%2) == 0) ? LOCAL_STATE+1 : LOCAL_STATE+2; 1677c478bd9Sstevel@tonic-gate 1687c478bd9Sstevel@tonic-gate /* IF local state overflows, reset to value 1 */ 1697c478bd9Sstevel@tonic-gate if (LOCAL_STATE < 0) { 1707c478bd9Sstevel@tonic-gate LOCAL_STATE = 1; 1717c478bd9Sstevel@tonic-gate } 1727c478bd9Sstevel@tonic-gate 1737c478bd9Sstevel@tonic-gate /* Copy the LOCAL_STATE value back to all stat files */ 1747c478bd9Sstevel@tonic-gate if (fseek(fp, 0, 0) == -1) { 1757c478bd9Sstevel@tonic-gate syslog(LOG_ERR, "statd: fseek failed\n"); 1767c478bd9Sstevel@tonic-gate exit(1); 1777c478bd9Sstevel@tonic-gate } 1787c478bd9Sstevel@tonic-gate 1797c478bd9Sstevel@tonic-gate (void) fprintf(fp, "%-10d", LOCAL_STATE); 1807c478bd9Sstevel@tonic-gate (void) fflush(fp); 1817c478bd9Sstevel@tonic-gate if (fsync(fileno(fp)) == -1) { 1827c478bd9Sstevel@tonic-gate syslog(LOG_ERR, "statd: fsync failed\n"); 1837c478bd9Sstevel@tonic-gate exit(1); 1847c478bd9Sstevel@tonic-gate } 1857c478bd9Sstevel@tonic-gate (void) fclose(fp); 1867c478bd9Sstevel@tonic-gate 1877c478bd9Sstevel@tonic-gate for (i = 0; i < pathix; i++) { 1887c478bd9Sstevel@tonic-gate (void) sprintf(state_file, "%s/statmon/state", path_name[i]); 189*98573c19SMarcel Telka if ((fp_tmp = fopen(state_file, "r+")) == NULL) { 190*98573c19SMarcel Telka if ((fp_tmp = fopen(state_file, "w+")) == NULL) { 1917c478bd9Sstevel@tonic-gate syslog(LOG_ERR, 1927c478bd9Sstevel@tonic-gate "can't open %s: %m", state_file); 1937c478bd9Sstevel@tonic-gate continue; 1947c478bd9Sstevel@tonic-gate } else 1957c478bd9Sstevel@tonic-gate (void) chmod(state_file, 0644); 1967c478bd9Sstevel@tonic-gate } 1977c478bd9Sstevel@tonic-gate (void) fprintf(fp_tmp, "%-10d", LOCAL_STATE); 1987c478bd9Sstevel@tonic-gate (void) fflush(fp_tmp); 1997c478bd9Sstevel@tonic-gate if (fsync(fileno(fp_tmp)) == -1) { 2007c478bd9Sstevel@tonic-gate syslog(LOG_ERR, 2017c478bd9Sstevel@tonic-gate "statd: %s: fsync failed\n", state_file); 2027c478bd9Sstevel@tonic-gate (void) fclose(fp_tmp); 2037c478bd9Sstevel@tonic-gate exit(1); 2047c478bd9Sstevel@tonic-gate } 2057c478bd9Sstevel@tonic-gate (void) fclose(fp_tmp); 2067c478bd9Sstevel@tonic-gate } 2077c478bd9Sstevel@tonic-gate 2087c478bd9Sstevel@tonic-gate if (debug) 2097c478bd9Sstevel@tonic-gate (void) printf("local state = %d\n", LOCAL_STATE); 2107c478bd9Sstevel@tonic-gate 2117c478bd9Sstevel@tonic-gate if ((mkdir(CURRENT, SM_DIRECTORY_MODE)) == -1) { 2127c478bd9Sstevel@tonic-gate if (errno != EEXIST) { 2137c478bd9Sstevel@tonic-gate syslog(LOG_ERR, "statd: mkdir current, error %m\n"); 2147c478bd9Sstevel@tonic-gate exit(1); 2157c478bd9Sstevel@tonic-gate } 2167c478bd9Sstevel@tonic-gate } 2177c478bd9Sstevel@tonic-gate if ((mkdir(BACKUP, SM_DIRECTORY_MODE)) == -1) { 2187c478bd9Sstevel@tonic-gate if (errno != EEXIST) { 2197c478bd9Sstevel@tonic-gate syslog(LOG_ERR, "statd: mkdir backup, error %m\n"); 2207c478bd9Sstevel@tonic-gate exit(1); 2217c478bd9Sstevel@tonic-gate } 2227c478bd9Sstevel@tonic-gate } 2237c478bd9Sstevel@tonic-gate 2247c478bd9Sstevel@tonic-gate /* get all entries in CURRENT into BACKUP */ 225*98573c19SMarcel Telka if ((dp = opendir(CURRENT)) == NULL) { 2267c478bd9Sstevel@tonic-gate syslog(LOG_ERR, "statd: open current directory, error %m\n"); 2277c478bd9Sstevel@tonic-gate exit(1); 2287c478bd9Sstevel@tonic-gate } 2297c478bd9Sstevel@tonic-gate 2304bc0a2efScasper while ((dirp = readdir(dp)) != NULL) { 2317c478bd9Sstevel@tonic-gate if (strcmp(dirp->d_name, ".") != 0 && 2327c478bd9Sstevel@tonic-gate strcmp(dirp->d_name, "..") != 0) { 2337c478bd9Sstevel@tonic-gate /* rename all entries from CURRENT to BACKUP */ 2347c478bd9Sstevel@tonic-gate (void) move_file(CURRENT, dirp->d_name, BACKUP); 2357c478bd9Sstevel@tonic-gate } 2367c478bd9Sstevel@tonic-gate } 2377c478bd9Sstevel@tonic-gate 2387c478bd9Sstevel@tonic-gate (void) closedir(dp); 2397c478bd9Sstevel@tonic-gate 2407c478bd9Sstevel@tonic-gate /* Contact hosts' statd */ 241*98573c19SMarcel Telka if (thr_create(NULL, 0, (void *(*)(void *))thr_statd_init, NULL, 242*98573c19SMarcel Telka THR_DETACHED, NULL)) { 2437c478bd9Sstevel@tonic-gate syslog(LOG_ERR, 2447c478bd9Sstevel@tonic-gate "statd: unable to create thread for thr_statd_init\n"); 2457c478bd9Sstevel@tonic-gate exit(1); 2467c478bd9Sstevel@tonic-gate } 2477c478bd9Sstevel@tonic-gate } 2487c478bd9Sstevel@tonic-gate 2497c478bd9Sstevel@tonic-gate /* 2507c478bd9Sstevel@tonic-gate * Work thread which contacts hosts' statd. 2517c478bd9Sstevel@tonic-gate */ 252*98573c19SMarcel Telka static void * 253*98573c19SMarcel Telka thr_statd_init(void) 2547c478bd9Sstevel@tonic-gate { 2554bc0a2efScasper struct dirent *dirp; 2567c478bd9Sstevel@tonic-gate DIR *dp; 2577c478bd9Sstevel@tonic-gate int num_threads; 2587c478bd9Sstevel@tonic-gate int num_join; 2597c478bd9Sstevel@tonic-gate int i; 2607c478bd9Sstevel@tonic-gate char *name; 2617c478bd9Sstevel@tonic-gate char buf[MAXPATHLEN+SM_MAXPATHLEN]; 2627c478bd9Sstevel@tonic-gate 2637c478bd9Sstevel@tonic-gate /* Go thru backup directory and contact hosts */ 264*98573c19SMarcel Telka if ((dp = opendir(BACKUP)) == NULL) { 2657c478bd9Sstevel@tonic-gate syslog(LOG_ERR, "statd: open backup directory, error %m\n"); 2667c478bd9Sstevel@tonic-gate exit(1); 2677c478bd9Sstevel@tonic-gate } 2687c478bd9Sstevel@tonic-gate 2697c478bd9Sstevel@tonic-gate /* 2707c478bd9Sstevel@tonic-gate * Create "UNDETACHED" threads for each symlink and (unlinked) 2717c478bd9Sstevel@tonic-gate * regular file in backup directory to initiate statd_call_statd. 2727c478bd9Sstevel@tonic-gate * NOTE: These threads are the only undetached threads in this 2737c478bd9Sstevel@tonic-gate * program and thus, the thread id is not needed to join the threads. 2747c478bd9Sstevel@tonic-gate */ 2757c478bd9Sstevel@tonic-gate num_threads = 0; 2764bc0a2efScasper while ((dirp = readdir(dp)) != NULL) { 2777c478bd9Sstevel@tonic-gate /* 2787c478bd9Sstevel@tonic-gate * If host file is not a symlink, don't bother to 2797c478bd9Sstevel@tonic-gate * spawn a thread for it. If any link(s) refer to 2807c478bd9Sstevel@tonic-gate * it, the host will be contacted using the link(s). 2817c478bd9Sstevel@tonic-gate * If not, we'll deal with it during the legacy pass. 2827c478bd9Sstevel@tonic-gate */ 2837c478bd9Sstevel@tonic-gate (void) sprintf(buf, "%s/%s", BACKUP, dirp->d_name); 2847c478bd9Sstevel@tonic-gate if (is_symlink(buf) == 0) { 2857c478bd9Sstevel@tonic-gate continue; 2867c478bd9Sstevel@tonic-gate } 2877c478bd9Sstevel@tonic-gate 2887c478bd9Sstevel@tonic-gate /* 2897c478bd9Sstevel@tonic-gate * If the num_threads has exceeded, wait until 2907c478bd9Sstevel@tonic-gate * a certain amount of threads have finished. 2917c478bd9Sstevel@tonic-gate * Currently, 10% of threads created should be joined. 2927c478bd9Sstevel@tonic-gate */ 2937c478bd9Sstevel@tonic-gate if (num_threads > MAX_THR) { 2947c478bd9Sstevel@tonic-gate num_join = num_threads/PERCENT_MINJOIN; 2957c478bd9Sstevel@tonic-gate for (i = 0; i < num_join; i++) 2967c478bd9Sstevel@tonic-gate thr_join(0, 0, 0); 2977c478bd9Sstevel@tonic-gate num_threads -= num_join; 2987c478bd9Sstevel@tonic-gate } 2997c478bd9Sstevel@tonic-gate 3007c478bd9Sstevel@tonic-gate /* 3017c478bd9Sstevel@tonic-gate * If can't alloc name then print error msg and 3027c478bd9Sstevel@tonic-gate * continue to next item on list. 3037c478bd9Sstevel@tonic-gate */ 3047c478bd9Sstevel@tonic-gate name = strdup(dirp->d_name); 305*98573c19SMarcel Telka if (name == NULL) { 3067c478bd9Sstevel@tonic-gate syslog(LOG_ERR, 3077c478bd9Sstevel@tonic-gate "statd: unable to allocate space for name %s\n", 3087c478bd9Sstevel@tonic-gate dirp->d_name); 3097c478bd9Sstevel@tonic-gate continue; 3107c478bd9Sstevel@tonic-gate } 3117c478bd9Sstevel@tonic-gate 3127c478bd9Sstevel@tonic-gate /* Create a thread to do a statd_call_statd for name */ 313*98573c19SMarcel Telka if (thr_create(NULL, 0, thr_call_statd, name, 0, NULL)) { 3147c478bd9Sstevel@tonic-gate syslog(LOG_ERR, 315bbaa8b60SDan Kruchinin "statd: unable to create thr_call_statd() " 316bbaa8b60SDan Kruchinin "for name %s.\n", dirp->d_name); 3177c478bd9Sstevel@tonic-gate free(name); 3187c478bd9Sstevel@tonic-gate continue; 3197c478bd9Sstevel@tonic-gate } 3207c478bd9Sstevel@tonic-gate num_threads++; 3217c478bd9Sstevel@tonic-gate } 3227c478bd9Sstevel@tonic-gate 3237c478bd9Sstevel@tonic-gate /* 3247c478bd9Sstevel@tonic-gate * Join the other threads created above before processing the 3257c478bd9Sstevel@tonic-gate * legacies. This allows all symlinks and the regular files 3267c478bd9Sstevel@tonic-gate * to which they correspond to be processed and deleted. 3277c478bd9Sstevel@tonic-gate */ 3287c478bd9Sstevel@tonic-gate for (i = 0; i < num_threads; i++) { 3297c478bd9Sstevel@tonic-gate thr_join(0, 0, 0); 3307c478bd9Sstevel@tonic-gate } 3317c478bd9Sstevel@tonic-gate 3327c478bd9Sstevel@tonic-gate /* 3337c478bd9Sstevel@tonic-gate * The second pass checks for `legacies': regular files which 3347c478bd9Sstevel@tonic-gate * never had symlinks pointing to them at all, just like in the 3357c478bd9Sstevel@tonic-gate * good old (pre-1184192 fix) days. Once a machine has cleaned 3367c478bd9Sstevel@tonic-gate * up its legacies they should only reoccur due to catastrophes 3377c478bd9Sstevel@tonic-gate * (e.g., severed symlinks). 3387c478bd9Sstevel@tonic-gate */ 3397c478bd9Sstevel@tonic-gate rewinddir(dp); 3407c478bd9Sstevel@tonic-gate num_threads = 0; 3414bc0a2efScasper while ((dirp = readdir(dp)) != NULL) { 3427c478bd9Sstevel@tonic-gate if (strcmp(dirp->d_name, ".") == 0 || 3437c478bd9Sstevel@tonic-gate strcmp(dirp->d_name, "..") == 0) { 3447c478bd9Sstevel@tonic-gate continue; 3457c478bd9Sstevel@tonic-gate } 3467c478bd9Sstevel@tonic-gate 3477c478bd9Sstevel@tonic-gate (void) sprintf(buf, "%s/%s", BACKUP, dirp->d_name); 3487c478bd9Sstevel@tonic-gate if (is_symlink(buf)) { 3497c478bd9Sstevel@tonic-gate /* 3507c478bd9Sstevel@tonic-gate * We probably couldn't reach this host and it's 3517c478bd9Sstevel@tonic-gate * been put on the recovery queue for retry. 3527c478bd9Sstevel@tonic-gate * Skip it and keep looking for regular files. 3537c478bd9Sstevel@tonic-gate */ 3547c478bd9Sstevel@tonic-gate continue; 3557c478bd9Sstevel@tonic-gate } 3567c478bd9Sstevel@tonic-gate 3577c478bd9Sstevel@tonic-gate if (debug) { 3587c478bd9Sstevel@tonic-gate (void) printf("thr_statd_init: legacy %s\n", 3597c478bd9Sstevel@tonic-gate dirp->d_name); 3607c478bd9Sstevel@tonic-gate } 3617c478bd9Sstevel@tonic-gate 3627c478bd9Sstevel@tonic-gate /* 3637c478bd9Sstevel@tonic-gate * If the number of threads exceeds the maximum, wait 3647c478bd9Sstevel@tonic-gate * for some fraction of them to finish before 3657c478bd9Sstevel@tonic-gate * continuing. 3667c478bd9Sstevel@tonic-gate */ 3677c478bd9Sstevel@tonic-gate if (num_threads > MAX_THR) { 3687c478bd9Sstevel@tonic-gate num_join = num_threads/PERCENT_MINJOIN; 3697c478bd9Sstevel@tonic-gate for (i = 0; i < num_join; i++) 3707c478bd9Sstevel@tonic-gate thr_join(0, 0, 0); 3717c478bd9Sstevel@tonic-gate num_threads -= num_join; 3727c478bd9Sstevel@tonic-gate } 3737c478bd9Sstevel@tonic-gate 3747c478bd9Sstevel@tonic-gate /* 3757c478bd9Sstevel@tonic-gate * If can't alloc name then print error msg and 3767c478bd9Sstevel@tonic-gate * continue to next item on list. 3777c478bd9Sstevel@tonic-gate */ 3787c478bd9Sstevel@tonic-gate name = strdup(dirp->d_name); 379*98573c19SMarcel Telka if (name == NULL) { 3807c478bd9Sstevel@tonic-gate syslog(LOG_ERR, 3817c478bd9Sstevel@tonic-gate "statd: unable to allocate space for name %s\n", 3827c478bd9Sstevel@tonic-gate dirp->d_name); 3837c478bd9Sstevel@tonic-gate continue; 3847c478bd9Sstevel@tonic-gate } 3857c478bd9Sstevel@tonic-gate 3867c478bd9Sstevel@tonic-gate /* Create a thread to do a statd_call_statd for name */ 387*98573c19SMarcel Telka if (thr_create(NULL, 0, thr_call_statd, name, 0, NULL)) { 3887c478bd9Sstevel@tonic-gate syslog(LOG_ERR, 389bbaa8b60SDan Kruchinin "statd: unable to create thr_call_statd() " 390bbaa8b60SDan Kruchinin "for name %s.\n", dirp->d_name); 3917c478bd9Sstevel@tonic-gate free(name); 3927c478bd9Sstevel@tonic-gate continue; 3937c478bd9Sstevel@tonic-gate } 3947c478bd9Sstevel@tonic-gate num_threads++; 3957c478bd9Sstevel@tonic-gate } 3967c478bd9Sstevel@tonic-gate 3977c478bd9Sstevel@tonic-gate (void) closedir(dp); 3987c478bd9Sstevel@tonic-gate 3997c478bd9Sstevel@tonic-gate /* 4007c478bd9Sstevel@tonic-gate * Join the other threads created above before creating thread 4017c478bd9Sstevel@tonic-gate * to process items in recovery table. 4027c478bd9Sstevel@tonic-gate */ 4037c478bd9Sstevel@tonic-gate for (i = 0; i < num_threads; i++) { 4047c478bd9Sstevel@tonic-gate thr_join(0, 0, 0); 4057c478bd9Sstevel@tonic-gate } 4067c478bd9Sstevel@tonic-gate 4077c478bd9Sstevel@tonic-gate /* 4087c478bd9Sstevel@tonic-gate * Need to only copy /var/statmon/sm.bak to alternate paths, since 4097c478bd9Sstevel@tonic-gate * the only hosts in /var/statmon/sm should be the ones currently 4107c478bd9Sstevel@tonic-gate * being monitored and already should be in alternate paths as part 4117c478bd9Sstevel@tonic-gate * of insert_mon(). 4127c478bd9Sstevel@tonic-gate */ 4137c478bd9Sstevel@tonic-gate for (i = 0; i < pathix; i++) { 4147c478bd9Sstevel@tonic-gate (void) sprintf(buf, "%s/statmon/sm.bak", path_name[i]); 4157c478bd9Sstevel@tonic-gate if ((mkdir(buf, SM_DIRECTORY_MODE)) == -1) { 4167c478bd9Sstevel@tonic-gate if (errno != EEXIST) 4177c478bd9Sstevel@tonic-gate syslog(LOG_ERR, "statd: mkdir %s error %m\n", 4187c478bd9Sstevel@tonic-gate buf); 4197c478bd9Sstevel@tonic-gate else 4207c478bd9Sstevel@tonic-gate copydir_from_to(BACKUP, buf); 4217c478bd9Sstevel@tonic-gate } else 4227c478bd9Sstevel@tonic-gate copydir_from_to(BACKUP, buf); 4237c478bd9Sstevel@tonic-gate } 4247c478bd9Sstevel@tonic-gate 4257c478bd9Sstevel@tonic-gate 4267c478bd9Sstevel@tonic-gate /* 427*98573c19SMarcel Telka * Reset the die and in_crash variables. 4287c478bd9Sstevel@tonic-gate */ 4297c478bd9Sstevel@tonic-gate mutex_lock(&crash_lock); 4307c478bd9Sstevel@tonic-gate die = 0; 4317c478bd9Sstevel@tonic-gate in_crash = 0; 4327c478bd9Sstevel@tonic-gate mutex_unlock(&crash_lock); 4337c478bd9Sstevel@tonic-gate 4347c478bd9Sstevel@tonic-gate if (debug) 4357c478bd9Sstevel@tonic-gate (void) printf("Creating thread for sm_try\n"); 4367c478bd9Sstevel@tonic-gate 4377c478bd9Sstevel@tonic-gate /* Continue to notify statd on hosts that were unreachable. */ 438*98573c19SMarcel Telka if (thr_create(NULL, 0, (void *(*)(void *))sm_try, NULL, THR_DETACHED, 439*98573c19SMarcel Telka NULL)) 4407c478bd9Sstevel@tonic-gate syslog(LOG_ERR, 4417c478bd9Sstevel@tonic-gate "statd: unable to create thread for sm_try().\n"); 4427c478bd9Sstevel@tonic-gate thr_exit((void *) 0); 4437c478bd9Sstevel@tonic-gate #ifdef lint 4447c478bd9Sstevel@tonic-gate return (0); 4457c478bd9Sstevel@tonic-gate #endif 4467c478bd9Sstevel@tonic-gate } 4477c478bd9Sstevel@tonic-gate 4487c478bd9Sstevel@tonic-gate /* 4497c478bd9Sstevel@tonic-gate * Work thread to make call to statd_call_statd. 4507c478bd9Sstevel@tonic-gate */ 4517c478bd9Sstevel@tonic-gate void * 4527c478bd9Sstevel@tonic-gate thr_call_statd(void *namep) 4537c478bd9Sstevel@tonic-gate { 4547c478bd9Sstevel@tonic-gate char *name = (char *)namep; 4557c478bd9Sstevel@tonic-gate 4567c478bd9Sstevel@tonic-gate /* 4577c478bd9Sstevel@tonic-gate * If statd of name is unreachable, add name to recovery table 4587c478bd9Sstevel@tonic-gate * otherwise if statd_call_statd was successful, remove from backup. 4597c478bd9Sstevel@tonic-gate */ 4607c478bd9Sstevel@tonic-gate if (statd_call_statd(name) != 0) { 4617c478bd9Sstevel@tonic-gate int n; 4627c478bd9Sstevel@tonic-gate char *tail; 4637c478bd9Sstevel@tonic-gate char path[MAXPATHLEN]; 4647c478bd9Sstevel@tonic-gate /* 4657c478bd9Sstevel@tonic-gate * since we are constructing this pathname below we add 4667c478bd9Sstevel@tonic-gate * another space for the terminating NULL so we don't 4677c478bd9Sstevel@tonic-gate * overflow our buffer when we do the readlink 4687c478bd9Sstevel@tonic-gate */ 4697c478bd9Sstevel@tonic-gate char rname[MAXNAMELEN + 1]; 4707c478bd9Sstevel@tonic-gate 4717c478bd9Sstevel@tonic-gate if (debug) { 4727c478bd9Sstevel@tonic-gate (void) printf( 4737c478bd9Sstevel@tonic-gate "statd call failed, inserting %s in recov_q\n", name); 4747c478bd9Sstevel@tonic-gate } 4757c478bd9Sstevel@tonic-gate mutex_lock(&recov_q.lock); 4767c478bd9Sstevel@tonic-gate (void) insert_name(&recov_q.sm_recovhdp, name, 0); 4777c478bd9Sstevel@tonic-gate mutex_unlock(&recov_q.lock); 4787c478bd9Sstevel@tonic-gate 4797c478bd9Sstevel@tonic-gate /* 4807c478bd9Sstevel@tonic-gate * If we queued a symlink name in the recovery queue, 4817c478bd9Sstevel@tonic-gate * we now clean up the regular file to which it referred. 4827c478bd9Sstevel@tonic-gate * This may leave a severed symlink if multiple links 4837c478bd9Sstevel@tonic-gate * referred to one regular file; this is unaesthetic but 4847c478bd9Sstevel@tonic-gate * it works. The big benefit is that it prevents us 4857c478bd9Sstevel@tonic-gate * from recovering the same host twice (as symlink and 4867c478bd9Sstevel@tonic-gate * as regular file) needlessly, usually on separate reboots. 4877c478bd9Sstevel@tonic-gate */ 4887c478bd9Sstevel@tonic-gate (void) strcpy(path, BACKUP); 4897c478bd9Sstevel@tonic-gate (void) strcat(path, "/"); 4907c478bd9Sstevel@tonic-gate (void) strcat(path, name); 4917c478bd9Sstevel@tonic-gate if (is_symlink(path)) { 4927c478bd9Sstevel@tonic-gate n = readlink(path, rname, MAXNAMELEN); 4937c478bd9Sstevel@tonic-gate if (n <= 0) { 4947c478bd9Sstevel@tonic-gate if (debug >= 2) { 4957c478bd9Sstevel@tonic-gate (void) printf( 496bbaa8b60SDan Kruchinin "thr_call_statd: can't read " 497bbaa8b60SDan Kruchinin "link %s\n", path); 4987c478bd9Sstevel@tonic-gate } 4997c478bd9Sstevel@tonic-gate } else { 5007c478bd9Sstevel@tonic-gate rname[n] = '\0'; 5017c478bd9Sstevel@tonic-gate 5027c478bd9Sstevel@tonic-gate tail = strrchr(path, '/') + 1; 5037c478bd9Sstevel@tonic-gate 5047c478bd9Sstevel@tonic-gate if ((strlen(BACKUP) + strlen(rname) + 2) <= 5057c478bd9Sstevel@tonic-gate MAXPATHLEN) { 5067c478bd9Sstevel@tonic-gate (void) strcpy(tail, rname); 5077c478bd9Sstevel@tonic-gate delete_file(path); 5087c478bd9Sstevel@tonic-gate } else if (debug) { 5097c478bd9Sstevel@tonic-gate printf("thr_call_statd: path over" 5107c478bd9Sstevel@tonic-gate "maxpathlen!\n"); 5117c478bd9Sstevel@tonic-gate } 5127c478bd9Sstevel@tonic-gate } 5137c478bd9Sstevel@tonic-gate 5147c478bd9Sstevel@tonic-gate } 5157c478bd9Sstevel@tonic-gate 5167c478bd9Sstevel@tonic-gate if (debug) 5177c478bd9Sstevel@tonic-gate pr_name(name, 0); 5187c478bd9Sstevel@tonic-gate 5197c478bd9Sstevel@tonic-gate } else { 5207c478bd9Sstevel@tonic-gate /* 5217c478bd9Sstevel@tonic-gate * If `name' is an IP address symlink to a name file, 5227c478bd9Sstevel@tonic-gate * remove it now. If it is the last such symlink, 5237c478bd9Sstevel@tonic-gate * remove the name file as well. Regular files with 5247c478bd9Sstevel@tonic-gate * no symlinks to them are assumed to be legacies and 5257c478bd9Sstevel@tonic-gate * are removed as well. 5267c478bd9Sstevel@tonic-gate */ 5277c478bd9Sstevel@tonic-gate remove_name(name, 1, 1); 5287c478bd9Sstevel@tonic-gate free(name); 5297c478bd9Sstevel@tonic-gate } 5307c478bd9Sstevel@tonic-gate thr_exit((void *) 0); 5317c478bd9Sstevel@tonic-gate #ifdef lint 5327c478bd9Sstevel@tonic-gate return (0); 5337c478bd9Sstevel@tonic-gate #endif 5347c478bd9Sstevel@tonic-gate } 5357c478bd9Sstevel@tonic-gate 5367c478bd9Sstevel@tonic-gate /* 5377c478bd9Sstevel@tonic-gate * Notifies the statd of host specified by name to indicate that 5387c478bd9Sstevel@tonic-gate * state has changed for this server. 5397c478bd9Sstevel@tonic-gate */ 5407c478bd9Sstevel@tonic-gate static int 541*98573c19SMarcel Telka statd_call_statd(char *name) 5427c478bd9Sstevel@tonic-gate { 5437c478bd9Sstevel@tonic-gate enum clnt_stat clnt_stat; 5447c478bd9Sstevel@tonic-gate struct timeval tottimeout; 5457c478bd9Sstevel@tonic-gate CLIENT *clnt; 5467c478bd9Sstevel@tonic-gate char *name_or_addr; 5477c478bd9Sstevel@tonic-gate stat_chge ntf; 5487c478bd9Sstevel@tonic-gate int i; 5497c478bd9Sstevel@tonic-gate int rc; 5507c478bd9Sstevel@tonic-gate int dummy1, dummy2, dummy3, dummy4; 5517c478bd9Sstevel@tonic-gate char ascii_addr[MAXNAMELEN]; 5527c478bd9Sstevel@tonic-gate size_t unq_len; 5537c478bd9Sstevel@tonic-gate 5547c478bd9Sstevel@tonic-gate ntf.mon_name = hostname; 5557c478bd9Sstevel@tonic-gate ntf.state = LOCAL_STATE; 5567c478bd9Sstevel@tonic-gate if (debug) 5577c478bd9Sstevel@tonic-gate (void) printf("statd_call_statd at %s\n", name); 5587c478bd9Sstevel@tonic-gate 5597c478bd9Sstevel@tonic-gate /* 5607c478bd9Sstevel@tonic-gate * If it looks like an ASCII <address family>.<address> specifier, 5617c478bd9Sstevel@tonic-gate * strip off the family - we just want the address when obtaining 5627c478bd9Sstevel@tonic-gate * a client handle. 5637c478bd9Sstevel@tonic-gate * If it's anything else, just pass it on to create_client(). 5647c478bd9Sstevel@tonic-gate */ 5657c478bd9Sstevel@tonic-gate unq_len = strcspn(name, "."); 5667c478bd9Sstevel@tonic-gate 5677c478bd9Sstevel@tonic-gate if ((strncmp(name, SM_ADDR_IPV4, unq_len) == 0) || 5687c478bd9Sstevel@tonic-gate (strncmp(name, SM_ADDR_IPV6, unq_len) == 0)) { 5697c478bd9Sstevel@tonic-gate name_or_addr = strchr(name, '.') + 1; 5707c478bd9Sstevel@tonic-gate } else { 5717c478bd9Sstevel@tonic-gate name_or_addr = name; 5727c478bd9Sstevel@tonic-gate } 5737c478bd9Sstevel@tonic-gate 5747c478bd9Sstevel@tonic-gate /* 5757c478bd9Sstevel@tonic-gate * NOTE: We depend here upon the fact that the RPC client code 5767c478bd9Sstevel@tonic-gate * allows us to use ASCII dotted quad `names', i.e. "192.9.200.1". 5777c478bd9Sstevel@tonic-gate * This may change in a future release. 5787c478bd9Sstevel@tonic-gate */ 5797c478bd9Sstevel@tonic-gate if (debug) { 5807c478bd9Sstevel@tonic-gate (void) printf("statd_call_statd: calling create_client(%s)\n", 5817c478bd9Sstevel@tonic-gate name_or_addr); 5827c478bd9Sstevel@tonic-gate } 5837c478bd9Sstevel@tonic-gate 5847c478bd9Sstevel@tonic-gate tottimeout.tv_sec = SM_RPC_TIMEOUT; 5857c478bd9Sstevel@tonic-gate tottimeout.tv_usec = 0; 5867c478bd9Sstevel@tonic-gate 587bbaa8b60SDan Kruchinin if ((clnt = create_client(name_or_addr, SM_PROG, SM_VERS, NULL, 588bbaa8b60SDan Kruchinin &tottimeout)) == NULL) { 589a6f0fae9Sgt29601 return (-1); 590a6f0fae9Sgt29601 } 591a6f0fae9Sgt29601 5927c478bd9Sstevel@tonic-gate /* Perform notification to client */ 5937c478bd9Sstevel@tonic-gate rc = 0; 5947c478bd9Sstevel@tonic-gate clnt_stat = clnt_call(clnt, SM_NOTIFY, xdr_stat_chge, (char *)&ntf, 5957c478bd9Sstevel@tonic-gate xdr_void, NULL, tottimeout); 5967c478bd9Sstevel@tonic-gate if (debug) { 5977c478bd9Sstevel@tonic-gate (void) printf("clnt_stat=%s(%d)\n", 5987c478bd9Sstevel@tonic-gate clnt_sperrno(clnt_stat), clnt_stat); 5997c478bd9Sstevel@tonic-gate } 6007c478bd9Sstevel@tonic-gate if (clnt_stat != (int)RPC_SUCCESS) { 6017c478bd9Sstevel@tonic-gate syslog(LOG_WARNING, 6027c478bd9Sstevel@tonic-gate "statd: cannot talk to statd at %s, %s(%d)\n", 6037c478bd9Sstevel@tonic-gate name_or_addr, clnt_sperrno(clnt_stat), clnt_stat); 6047c478bd9Sstevel@tonic-gate rc = -1; 6057c478bd9Sstevel@tonic-gate } 6067c478bd9Sstevel@tonic-gate 607*98573c19SMarcel Telka /* 608*98573c19SMarcel Telka * Wait until the host_name is populated. 609*98573c19SMarcel Telka */ 610*98573c19SMarcel Telka (void) mutex_lock(&merges_lock); 611*98573c19SMarcel Telka while (in_merges) 612*98573c19SMarcel Telka (void) cond_wait(&merges_cond, &merges_lock); 613*98573c19SMarcel Telka (void) mutex_unlock(&merges_lock); 614*98573c19SMarcel Telka 6157c478bd9Sstevel@tonic-gate /* For HA systems and multi-homed hosts */ 6167c478bd9Sstevel@tonic-gate ntf.state = LOCAL_STATE; 6177c478bd9Sstevel@tonic-gate for (i = 0; i < addrix; i++) { 6187c478bd9Sstevel@tonic-gate ntf.mon_name = host_name[i]; 6197c478bd9Sstevel@tonic-gate if (debug) 6207c478bd9Sstevel@tonic-gate (void) printf("statd_call_statd at %s\n", name_or_addr); 6217c478bd9Sstevel@tonic-gate clnt_stat = clnt_call(clnt, SM_NOTIFY, xdr_stat_chge, 622*98573c19SMarcel Telka (char *)&ntf, xdr_void, NULL, tottimeout); 6237c478bd9Sstevel@tonic-gate if (clnt_stat != (int)RPC_SUCCESS) { 6247c478bd9Sstevel@tonic-gate syslog(LOG_WARNING, 6257c478bd9Sstevel@tonic-gate "statd: cannot talk to statd at %s, %s(%d)\n", 6267c478bd9Sstevel@tonic-gate name_or_addr, clnt_sperrno(clnt_stat), clnt_stat); 6277c478bd9Sstevel@tonic-gate rc = -1; 6287c478bd9Sstevel@tonic-gate } 6297c478bd9Sstevel@tonic-gate } 6307c478bd9Sstevel@tonic-gate clnt_destroy(clnt); 6317c478bd9Sstevel@tonic-gate return (rc); 6327c478bd9Sstevel@tonic-gate } 6337c478bd9Sstevel@tonic-gate 6347c478bd9Sstevel@tonic-gate /* 6357c478bd9Sstevel@tonic-gate * Continues to contact hosts in recovery table that were unreachable. 6367c478bd9Sstevel@tonic-gate * NOTE: There should only be one sm_try thread executing and 6377c478bd9Sstevel@tonic-gate * thus locks are not needed for recovery table. Die is only cleared 6387c478bd9Sstevel@tonic-gate * after all the hosts has at least been contacted once. The reader/writer 6397c478bd9Sstevel@tonic-gate * lock ensures to finish this code before an sm_crash is started. Die 6407c478bd9Sstevel@tonic-gate * variable will signal it. 6417c478bd9Sstevel@tonic-gate */ 6427c478bd9Sstevel@tonic-gate void * 643*98573c19SMarcel Telka sm_try(void) 6447c478bd9Sstevel@tonic-gate { 6457c478bd9Sstevel@tonic-gate name_entry *nl, *next; 6467c478bd9Sstevel@tonic-gate timestruc_t wtime; 6477c478bd9Sstevel@tonic-gate int delay = 0; 6487c478bd9Sstevel@tonic-gate 6497c478bd9Sstevel@tonic-gate rw_rdlock(&thr_rwlock); 6507c478bd9Sstevel@tonic-gate if (mutex_trylock(&sm_trylock)) 6517c478bd9Sstevel@tonic-gate goto out; 6527c478bd9Sstevel@tonic-gate mutex_lock(&crash_lock); 6537c478bd9Sstevel@tonic-gate 6547c478bd9Sstevel@tonic-gate while (!die) { 6557c478bd9Sstevel@tonic-gate wtime.tv_sec = delay; 6567c478bd9Sstevel@tonic-gate wtime.tv_nsec = 0; 6577c478bd9Sstevel@tonic-gate /* 6587c478bd9Sstevel@tonic-gate * Wait until signalled to wakeup or time expired. 6597c478bd9Sstevel@tonic-gate * If signalled to be awoken, then a crash has occurred 6607c478bd9Sstevel@tonic-gate * or otherwise time expired. 6617c478bd9Sstevel@tonic-gate */ 6627c478bd9Sstevel@tonic-gate if (cond_reltimedwait(&retrywait, &crash_lock, &wtime) == 0) { 6637c478bd9Sstevel@tonic-gate break; 6647c478bd9Sstevel@tonic-gate } 6657c478bd9Sstevel@tonic-gate 6667c478bd9Sstevel@tonic-gate /* Exit loop if queue is empty */ 6677c478bd9Sstevel@tonic-gate if ((next = recov_q.sm_recovhdp) == NULL) 6687c478bd9Sstevel@tonic-gate break; 6697c478bd9Sstevel@tonic-gate 6707c478bd9Sstevel@tonic-gate mutex_unlock(&crash_lock); 6717c478bd9Sstevel@tonic-gate 672*98573c19SMarcel Telka while (((nl = next) != NULL) && (!die)) { 6737c478bd9Sstevel@tonic-gate next = next->nxt; 6747c478bd9Sstevel@tonic-gate if (statd_call_statd(nl->name) == 0) { 6757c478bd9Sstevel@tonic-gate /* remove name from BACKUP */ 6767c478bd9Sstevel@tonic-gate remove_name(nl->name, 1, 0); 6777c478bd9Sstevel@tonic-gate mutex_lock(&recov_q.lock); 6787c478bd9Sstevel@tonic-gate /* remove entry from recovery_q */ 6797c478bd9Sstevel@tonic-gate delete_name(&recov_q.sm_recovhdp, nl->name); 6807c478bd9Sstevel@tonic-gate mutex_unlock(&recov_q.lock); 6817c478bd9Sstevel@tonic-gate } else { 6827c478bd9Sstevel@tonic-gate /* 6837c478bd9Sstevel@tonic-gate * Print message only once since unreachable 6847c478bd9Sstevel@tonic-gate * host can be contacted forever. 6857c478bd9Sstevel@tonic-gate */ 6867c478bd9Sstevel@tonic-gate if (delay == 0) 6877c478bd9Sstevel@tonic-gate syslog(LOG_WARNING, 688bbaa8b60SDan Kruchinin "statd: host %s is not " 689bbaa8b60SDan Kruchinin "responding\n", nl->name); 6907c478bd9Sstevel@tonic-gate } 6917c478bd9Sstevel@tonic-gate } 6927c478bd9Sstevel@tonic-gate /* 6937c478bd9Sstevel@tonic-gate * Increment the amount of delay before restarting again. 6947c478bd9Sstevel@tonic-gate * The amount of delay should not exceed the MAX_DELAYTIME. 6957c478bd9Sstevel@tonic-gate */ 6967c478bd9Sstevel@tonic-gate if (delay <= MAX_DELAYTIME) 6977c478bd9Sstevel@tonic-gate delay += INC_DELAYTIME; 6987c478bd9Sstevel@tonic-gate mutex_lock(&crash_lock); 6997c478bd9Sstevel@tonic-gate } 7007c478bd9Sstevel@tonic-gate 7017c478bd9Sstevel@tonic-gate mutex_unlock(&crash_lock); 7027c478bd9Sstevel@tonic-gate mutex_unlock(&sm_trylock); 7037c478bd9Sstevel@tonic-gate out: 7047c478bd9Sstevel@tonic-gate rw_unlock(&thr_rwlock); 7057c478bd9Sstevel@tonic-gate if (debug) 7067c478bd9Sstevel@tonic-gate (void) printf("EXITING sm_try\n"); 7077c478bd9Sstevel@tonic-gate thr_exit((void *) 0); 7087c478bd9Sstevel@tonic-gate #ifdef lint 7097c478bd9Sstevel@tonic-gate return (0); 7107c478bd9Sstevel@tonic-gate #endif 7117c478bd9Sstevel@tonic-gate } 7127c478bd9Sstevel@tonic-gate 7137c478bd9Sstevel@tonic-gate /* 7147c478bd9Sstevel@tonic-gate * Malloc's space and returns the ptr to malloc'ed space. NULL if unsuccessful. 7157c478bd9Sstevel@tonic-gate */ 7167c478bd9Sstevel@tonic-gate char * 717*98573c19SMarcel Telka xmalloc(unsigned len) 7187c478bd9Sstevel@tonic-gate { 7197c478bd9Sstevel@tonic-gate char *new; 7207c478bd9Sstevel@tonic-gate 7217c478bd9Sstevel@tonic-gate if ((new = malloc(len)) == 0) { 7227c478bd9Sstevel@tonic-gate syslog(LOG_ERR, "statd: malloc, error %m\n"); 723*98573c19SMarcel Telka return (NULL); 7247c478bd9Sstevel@tonic-gate } else { 7257c478bd9Sstevel@tonic-gate (void) memset(new, 0, len); 7267c478bd9Sstevel@tonic-gate return (new); 7277c478bd9Sstevel@tonic-gate } 7287c478bd9Sstevel@tonic-gate } 7297c478bd9Sstevel@tonic-gate 7307c478bd9Sstevel@tonic-gate /* 7317c478bd9Sstevel@tonic-gate * the following two routines are very similar to 7327c478bd9Sstevel@tonic-gate * insert_mon and delete_mon in sm_proc.c, except the structture 7337c478bd9Sstevel@tonic-gate * is different 7347c478bd9Sstevel@tonic-gate */ 7357c478bd9Sstevel@tonic-gate static name_entry * 736*98573c19SMarcel Telka insert_name(name_entry **namepp, char *name, int need_alloc) 7377c478bd9Sstevel@tonic-gate { 7387c478bd9Sstevel@tonic-gate name_entry *new; 7397c478bd9Sstevel@tonic-gate 7407c478bd9Sstevel@tonic-gate new = (name_entry *)xmalloc(sizeof (name_entry)); 7417c478bd9Sstevel@tonic-gate if (new == (name_entry *) NULL) 7427c478bd9Sstevel@tonic-gate return (NULL); 7437c478bd9Sstevel@tonic-gate 7447c478bd9Sstevel@tonic-gate /* Allocate name when needed which is only when adding to record_t */ 7457c478bd9Sstevel@tonic-gate if (need_alloc) { 746*98573c19SMarcel Telka if ((new->name = strdup(name)) == NULL) { 7477c478bd9Sstevel@tonic-gate syslog(LOG_ERR, "statd: strdup, error %m\n"); 7487c478bd9Sstevel@tonic-gate free(new); 7497c478bd9Sstevel@tonic-gate return (NULL); 7507c478bd9Sstevel@tonic-gate } 7517c478bd9Sstevel@tonic-gate } else 7527c478bd9Sstevel@tonic-gate new->name = name; 7537c478bd9Sstevel@tonic-gate 7547c478bd9Sstevel@tonic-gate new->nxt = *namepp; 755*98573c19SMarcel Telka if (new->nxt != NULL) 7567c478bd9Sstevel@tonic-gate new->nxt->prev = new; 7577c478bd9Sstevel@tonic-gate 7587c478bd9Sstevel@tonic-gate new->prev = (name_entry *) NULL; 7597c478bd9Sstevel@tonic-gate 7607c478bd9Sstevel@tonic-gate *namepp = new; 7617c478bd9Sstevel@tonic-gate if (debug) { 7627c478bd9Sstevel@tonic-gate (void) printf("insert_name: inserted %s at %p\n", 7637c478bd9Sstevel@tonic-gate name, (void *)namepp); 7647c478bd9Sstevel@tonic-gate } 7657c478bd9Sstevel@tonic-gate 7667c478bd9Sstevel@tonic-gate return (new); 7677c478bd9Sstevel@tonic-gate } 7687c478bd9Sstevel@tonic-gate 7697c478bd9Sstevel@tonic-gate /* 7707c478bd9Sstevel@tonic-gate * Deletes name from specified list (namepp). 7717c478bd9Sstevel@tonic-gate */ 7727c478bd9Sstevel@tonic-gate static void 773*98573c19SMarcel Telka delete_name(name_entry **namepp, char *name) 7747c478bd9Sstevel@tonic-gate { 7757c478bd9Sstevel@tonic-gate name_entry *nl; 7767c478bd9Sstevel@tonic-gate 7777c478bd9Sstevel@tonic-gate nl = *namepp; 778*98573c19SMarcel Telka while (nl != NULL) { 7797c478bd9Sstevel@tonic-gate if (str_cmp_address_specifier(nl->name, name) == 0 || 7807c478bd9Sstevel@tonic-gate str_cmp_unqual_hostname(nl->name, name) == 0) { 781*98573c19SMarcel Telka if (nl->prev != NULL) 7827c478bd9Sstevel@tonic-gate nl->prev->nxt = nl->nxt; 7837c478bd9Sstevel@tonic-gate else 7847c478bd9Sstevel@tonic-gate *namepp = nl->nxt; 785*98573c19SMarcel Telka if (nl->nxt != NULL) 7867c478bd9Sstevel@tonic-gate nl->nxt->prev = nl->prev; 7877c478bd9Sstevel@tonic-gate free(nl->name); 7887c478bd9Sstevel@tonic-gate free(nl); 7897c478bd9Sstevel@tonic-gate return; 7907c478bd9Sstevel@tonic-gate } 7917c478bd9Sstevel@tonic-gate nl = nl->nxt; 7927c478bd9Sstevel@tonic-gate } 7937c478bd9Sstevel@tonic-gate } 7947c478bd9Sstevel@tonic-gate 7957c478bd9Sstevel@tonic-gate /* 7967c478bd9Sstevel@tonic-gate * Finds name from specified list (namep). 7977c478bd9Sstevel@tonic-gate */ 7987c478bd9Sstevel@tonic-gate static name_entry * 799*98573c19SMarcel Telka find_name(name_entry **namep, char *name) 8007c478bd9Sstevel@tonic-gate { 8017c478bd9Sstevel@tonic-gate name_entry *nl; 8027c478bd9Sstevel@tonic-gate 8037c478bd9Sstevel@tonic-gate nl = *namep; 8047c478bd9Sstevel@tonic-gate 805*98573c19SMarcel Telka while (nl != NULL) { 8067c478bd9Sstevel@tonic-gate if (str_cmp_unqual_hostname(nl->name, name) == 0) { 8077c478bd9Sstevel@tonic-gate return (nl); 8087c478bd9Sstevel@tonic-gate } 8097c478bd9Sstevel@tonic-gate nl = nl->nxt; 8107c478bd9Sstevel@tonic-gate } 811*98573c19SMarcel Telka return (NULL); 8127c478bd9Sstevel@tonic-gate } 8137c478bd9Sstevel@tonic-gate 8147c478bd9Sstevel@tonic-gate /* 8157c478bd9Sstevel@tonic-gate * Creates a file. 8167c478bd9Sstevel@tonic-gate */ 8177c478bd9Sstevel@tonic-gate 8187c478bd9Sstevel@tonic-gate int 819*98573c19SMarcel Telka create_file(char *name) 8207c478bd9Sstevel@tonic-gate { 8217c478bd9Sstevel@tonic-gate int fd; 8227c478bd9Sstevel@tonic-gate 8237c478bd9Sstevel@tonic-gate /* 8247c478bd9Sstevel@tonic-gate * The file might already exist. If it does, we ask for only write 8257c478bd9Sstevel@tonic-gate * permission, since that's all the file was created with. 8267c478bd9Sstevel@tonic-gate */ 8277c478bd9Sstevel@tonic-gate if ((fd = open(name, O_CREAT | O_WRONLY, S_IWUSR)) == -1) { 8287c478bd9Sstevel@tonic-gate if (errno != EEXIST) { 8297c478bd9Sstevel@tonic-gate syslog(LOG_ERR, "can't open %s: %m", name); 8307c478bd9Sstevel@tonic-gate return (1); 8317c478bd9Sstevel@tonic-gate } 8327c478bd9Sstevel@tonic-gate } 8337c478bd9Sstevel@tonic-gate 8347c478bd9Sstevel@tonic-gate if (debug >= 2) 8357c478bd9Sstevel@tonic-gate (void) printf("%s is created\n", name); 8367c478bd9Sstevel@tonic-gate if (close(fd)) { 8377c478bd9Sstevel@tonic-gate syslog(LOG_ERR, "statd: close, error %m\n"); 8387c478bd9Sstevel@tonic-gate return (1); 8397c478bd9Sstevel@tonic-gate } 8407c478bd9Sstevel@tonic-gate 8417c478bd9Sstevel@tonic-gate return (0); 8427c478bd9Sstevel@tonic-gate } 8437c478bd9Sstevel@tonic-gate 8447c478bd9Sstevel@tonic-gate /* 8457c478bd9Sstevel@tonic-gate * Deletes the file specified by name. 8467c478bd9Sstevel@tonic-gate */ 8477c478bd9Sstevel@tonic-gate void 848*98573c19SMarcel Telka delete_file(char *name) 8497c478bd9Sstevel@tonic-gate { 8507c478bd9Sstevel@tonic-gate if (debug >= 2) 8517c478bd9Sstevel@tonic-gate (void) printf("Remove monitor entry %s\n", name); 8527c478bd9Sstevel@tonic-gate if (unlink(name) == -1) { 8537c478bd9Sstevel@tonic-gate if (errno != ENOENT) 8547c478bd9Sstevel@tonic-gate syslog(LOG_ERR, "statd: unlink of %s, error %m", name); 8557c478bd9Sstevel@tonic-gate } 8567c478bd9Sstevel@tonic-gate } 8577c478bd9Sstevel@tonic-gate 8587c478bd9Sstevel@tonic-gate /* 8597c478bd9Sstevel@tonic-gate * Return 1 if file is a symlink, else 0. 8607c478bd9Sstevel@tonic-gate */ 8617c478bd9Sstevel@tonic-gate int 862*98573c19SMarcel Telka is_symlink(char *file) 8637c478bd9Sstevel@tonic-gate { 8647c478bd9Sstevel@tonic-gate int error; 8657c478bd9Sstevel@tonic-gate struct stat lbuf; 8667c478bd9Sstevel@tonic-gate 8677c478bd9Sstevel@tonic-gate do { 8687c478bd9Sstevel@tonic-gate bzero((caddr_t)&lbuf, sizeof (lbuf)); 8697c478bd9Sstevel@tonic-gate error = lstat(file, &lbuf); 8707c478bd9Sstevel@tonic-gate } while (error == EINTR); 8717c478bd9Sstevel@tonic-gate 8727c478bd9Sstevel@tonic-gate if (error == 0) { 8737c478bd9Sstevel@tonic-gate return ((lbuf.st_mode & S_IFMT) == S_IFLNK); 8747c478bd9Sstevel@tonic-gate } 8757c478bd9Sstevel@tonic-gate 8767c478bd9Sstevel@tonic-gate return (0); 8777c478bd9Sstevel@tonic-gate } 8787c478bd9Sstevel@tonic-gate 8797c478bd9Sstevel@tonic-gate /* 8807c478bd9Sstevel@tonic-gate * Moves the file specified by `from' to `to' only if the 8817c478bd9Sstevel@tonic-gate * new file is guaranteed to be created (which is presumably 8827c478bd9Sstevel@tonic-gate * why we don't just do a rename(2)). If `from' is a 8837c478bd9Sstevel@tonic-gate * symlink, the destination file will be a similar symlink 8847c478bd9Sstevel@tonic-gate * in the directory of `to'. 8857c478bd9Sstevel@tonic-gate * 8867c478bd9Sstevel@tonic-gate * Returns 0 for success, 1 for failure. 8877c478bd9Sstevel@tonic-gate */ 8887c478bd9Sstevel@tonic-gate static int 889*98573c19SMarcel Telka move_file(char *fromdir, char *file, char *todir) 8907c478bd9Sstevel@tonic-gate { 8917c478bd9Sstevel@tonic-gate int n; 8927c478bd9Sstevel@tonic-gate char rname[MAXNAMELEN + 1]; /* +1 for the terminating NULL */ 8937c478bd9Sstevel@tonic-gate char from[MAXPATHLEN]; 8947c478bd9Sstevel@tonic-gate char to[MAXPATHLEN]; 8957c478bd9Sstevel@tonic-gate 8967c478bd9Sstevel@tonic-gate (void) strcpy(from, fromdir); 8977c478bd9Sstevel@tonic-gate (void) strcat(from, "/"); 8987c478bd9Sstevel@tonic-gate (void) strcat(from, file); 8997c478bd9Sstevel@tonic-gate if (is_symlink(from)) { 9007c478bd9Sstevel@tonic-gate /* 9017c478bd9Sstevel@tonic-gate * Dig out the name of the regular file the link points to. 9027c478bd9Sstevel@tonic-gate */ 9037c478bd9Sstevel@tonic-gate n = readlink(from, rname, MAXNAMELEN); 9047c478bd9Sstevel@tonic-gate if (n <= 0) { 9057c478bd9Sstevel@tonic-gate if (debug >= 2) { 9067c478bd9Sstevel@tonic-gate (void) printf("move_file: can't read link %s\n", 9077c478bd9Sstevel@tonic-gate from); 9087c478bd9Sstevel@tonic-gate } 9097c478bd9Sstevel@tonic-gate return (1); 9107c478bd9Sstevel@tonic-gate } 9117c478bd9Sstevel@tonic-gate rname[n] = '\0'; 9127c478bd9Sstevel@tonic-gate 9137c478bd9Sstevel@tonic-gate /* 9147c478bd9Sstevel@tonic-gate * Create the link. 9157c478bd9Sstevel@tonic-gate */ 9167c478bd9Sstevel@tonic-gate if (create_symlink(todir, rname, file) != 0) { 9177c478bd9Sstevel@tonic-gate return (1); 9187c478bd9Sstevel@tonic-gate } 9197c478bd9Sstevel@tonic-gate } else { 9207c478bd9Sstevel@tonic-gate /* 9217c478bd9Sstevel@tonic-gate * Do what we've always done to move regular files. 9227c478bd9Sstevel@tonic-gate */ 9237c478bd9Sstevel@tonic-gate (void) strcpy(to, todir); 9247c478bd9Sstevel@tonic-gate (void) strcat(to, "/"); 9257c478bd9Sstevel@tonic-gate (void) strcat(to, file); 9267c478bd9Sstevel@tonic-gate if (create_file(to) != 0) { 9277c478bd9Sstevel@tonic-gate return (1); 9287c478bd9Sstevel@tonic-gate } 9297c478bd9Sstevel@tonic-gate } 9307c478bd9Sstevel@tonic-gate 9317c478bd9Sstevel@tonic-gate /* 9327c478bd9Sstevel@tonic-gate * Remove the old file if we've created the new one. 9337c478bd9Sstevel@tonic-gate */ 9347c478bd9Sstevel@tonic-gate if (unlink(from) < 0) { 9357c478bd9Sstevel@tonic-gate syslog(LOG_ERR, "move_file: unlink of %s, error %m", from); 9367c478bd9Sstevel@tonic-gate return (1); 9377c478bd9Sstevel@tonic-gate } 9387c478bd9Sstevel@tonic-gate 9397c478bd9Sstevel@tonic-gate return (0); 9407c478bd9Sstevel@tonic-gate } 9417c478bd9Sstevel@tonic-gate 9427c478bd9Sstevel@tonic-gate /* 9437c478bd9Sstevel@tonic-gate * Create a symbolic link named `lname' to regular file `rname'. 9447c478bd9Sstevel@tonic-gate * Both files should be in directory `todir'. 9457c478bd9Sstevel@tonic-gate */ 9467c478bd9Sstevel@tonic-gate int 947*98573c19SMarcel Telka create_symlink(char *todir, char *rname, char *lname) 9487c478bd9Sstevel@tonic-gate { 9497c478bd9Sstevel@tonic-gate int error; 9507c478bd9Sstevel@tonic-gate char lpath[MAXPATHLEN]; 9517c478bd9Sstevel@tonic-gate 9527c478bd9Sstevel@tonic-gate /* 9537c478bd9Sstevel@tonic-gate * Form the full pathname of the link. 9547c478bd9Sstevel@tonic-gate */ 9557c478bd9Sstevel@tonic-gate (void) strcpy(lpath, todir); 9567c478bd9Sstevel@tonic-gate (void) strcat(lpath, "/"); 9577c478bd9Sstevel@tonic-gate (void) strcat(lpath, lname); 9587c478bd9Sstevel@tonic-gate 9597c478bd9Sstevel@tonic-gate /* 9607c478bd9Sstevel@tonic-gate * Now make the new symlink ... 9617c478bd9Sstevel@tonic-gate */ 9627c478bd9Sstevel@tonic-gate if (symlink(rname, lpath) < 0) { 9637c478bd9Sstevel@tonic-gate error = errno; 9647c478bd9Sstevel@tonic-gate if (error != 0 && error != EEXIST) { 9657c478bd9Sstevel@tonic-gate if (debug >= 2) { 966*98573c19SMarcel Telka (void) printf("create_symlink: can't link " 967*98573c19SMarcel Telka "%s/%s -> %s\n", todir, lname, rname); 9687c478bd9Sstevel@tonic-gate } 9697c478bd9Sstevel@tonic-gate return (1); 9707c478bd9Sstevel@tonic-gate } 9717c478bd9Sstevel@tonic-gate } 9727c478bd9Sstevel@tonic-gate 9737c478bd9Sstevel@tonic-gate if (debug) { 9747c478bd9Sstevel@tonic-gate if (error == EEXIST) { 9757c478bd9Sstevel@tonic-gate (void) printf("link %s/%s -> %s already exists\n", 9767c478bd9Sstevel@tonic-gate todir, lname, rname); 9777c478bd9Sstevel@tonic-gate } else { 9787c478bd9Sstevel@tonic-gate (void) printf("created link %s/%s -> %s\n", 9797c478bd9Sstevel@tonic-gate todir, lname, rname); 9807c478bd9Sstevel@tonic-gate } 9817c478bd9Sstevel@tonic-gate } 9827c478bd9Sstevel@tonic-gate 9837c478bd9Sstevel@tonic-gate return (0); 9847c478bd9Sstevel@tonic-gate } 9857c478bd9Sstevel@tonic-gate 9867c478bd9Sstevel@tonic-gate /* 9877c478bd9Sstevel@tonic-gate * remove the name from the specified directory 9887c478bd9Sstevel@tonic-gate * op = 0: CURRENT 9897c478bd9Sstevel@tonic-gate * op = 1: BACKUP 9907c478bd9Sstevel@tonic-gate */ 9917c478bd9Sstevel@tonic-gate static void 9927c478bd9Sstevel@tonic-gate remove_name(char *name, int op, int startup) 9937c478bd9Sstevel@tonic-gate { 9947c478bd9Sstevel@tonic-gate int i; 9957c478bd9Sstevel@tonic-gate char *alt_dir; 9967c478bd9Sstevel@tonic-gate char *queue; 9977c478bd9Sstevel@tonic-gate 9987c478bd9Sstevel@tonic-gate if (op == 0) { 9997c478bd9Sstevel@tonic-gate alt_dir = "statmon/sm"; 10007c478bd9Sstevel@tonic-gate queue = CURRENT; 10017c478bd9Sstevel@tonic-gate } else { 10027c478bd9Sstevel@tonic-gate alt_dir = "statmon/sm.bak"; 10037c478bd9Sstevel@tonic-gate queue = BACKUP; 10047c478bd9Sstevel@tonic-gate } 10057c478bd9Sstevel@tonic-gate 10067c478bd9Sstevel@tonic-gate remove_single_name(name, queue, NULL); 10077c478bd9Sstevel@tonic-gate /* 10087c478bd9Sstevel@tonic-gate * At startup, entries have not yet been copied to alternate 10097c478bd9Sstevel@tonic-gate * directories and thus do not need to be removed. 10107c478bd9Sstevel@tonic-gate */ 10117c478bd9Sstevel@tonic-gate if (startup == 0) { 10127c478bd9Sstevel@tonic-gate for (i = 0; i < pathix; i++) { 10137c478bd9Sstevel@tonic-gate remove_single_name(name, path_name[i], alt_dir); 10147c478bd9Sstevel@tonic-gate } 10157c478bd9Sstevel@tonic-gate } 10167c478bd9Sstevel@tonic-gate } 10177c478bd9Sstevel@tonic-gate 10187c478bd9Sstevel@tonic-gate /* 10197c478bd9Sstevel@tonic-gate * Remove the name from the specified directory, which is dir1/dir2 or 10207c478bd9Sstevel@tonic-gate * dir1, depending on whether dir2 is NULL. 10217c478bd9Sstevel@tonic-gate */ 10227c478bd9Sstevel@tonic-gate static void 10237c478bd9Sstevel@tonic-gate remove_single_name(char *name, char *dir1, char *dir2) 10247c478bd9Sstevel@tonic-gate { 10257c478bd9Sstevel@tonic-gate int n, error; 10267c478bd9Sstevel@tonic-gate char path[MAXPATHLEN+MAXNAMELEN+SM_MAXPATHLEN]; /* why > MAXPATHLEN? */ 10277c478bd9Sstevel@tonic-gate char dirpath[MAXPATHLEN]; 10287c478bd9Sstevel@tonic-gate char rname[MAXNAMELEN + 1]; /* +1 for NULL term */ 10297c478bd9Sstevel@tonic-gate 1030bbaa8b60SDan Kruchinin if (strlen(name) + strlen(dir1) + (dir2 != NULL ? strlen(dir2) : 0) + 1031bbaa8b60SDan Kruchinin 3 > MAXPATHLEN) { 10327c478bd9Sstevel@tonic-gate if (dir2 != NULL) 10337c478bd9Sstevel@tonic-gate syslog(LOG_ERR, 10347c478bd9Sstevel@tonic-gate "statd: pathname too long: %s/%s/%s\n", 10357c478bd9Sstevel@tonic-gate dir1, dir2, name); 10367c478bd9Sstevel@tonic-gate else 10377c478bd9Sstevel@tonic-gate syslog(LOG_ERR, 10387c478bd9Sstevel@tonic-gate "statd: pathname too long: %s/%s\n", 10397c478bd9Sstevel@tonic-gate dir1, name); 10407c478bd9Sstevel@tonic-gate 10417c478bd9Sstevel@tonic-gate return; 10427c478bd9Sstevel@tonic-gate } 10437c478bd9Sstevel@tonic-gate 10447c478bd9Sstevel@tonic-gate (void) strcpy(path, dir1); 10457c478bd9Sstevel@tonic-gate (void) strcat(path, "/"); 10467c478bd9Sstevel@tonic-gate if (dir2 != NULL) { 10477c478bd9Sstevel@tonic-gate (void) strcat(path, dir2); 10487c478bd9Sstevel@tonic-gate (void) strcat(path, "/"); 10497c478bd9Sstevel@tonic-gate } 10507c478bd9Sstevel@tonic-gate (void) strcpy(dirpath, path); /* save here - we may need it shortly */ 10517c478bd9Sstevel@tonic-gate (void) strcat(path, name); 10527c478bd9Sstevel@tonic-gate 10537c478bd9Sstevel@tonic-gate /* 10547c478bd9Sstevel@tonic-gate * Despite the name of this routine :-@), `path' may be a symlink 10557c478bd9Sstevel@tonic-gate * to a regular file. If it is, and if that file has no other 10567c478bd9Sstevel@tonic-gate * links to it, we must remove it now as well. 10577c478bd9Sstevel@tonic-gate */ 10587c478bd9Sstevel@tonic-gate if (is_symlink(path)) { 10597c478bd9Sstevel@tonic-gate n = readlink(path, rname, MAXNAMELEN); 10607c478bd9Sstevel@tonic-gate if (n > 0) { 10617c478bd9Sstevel@tonic-gate rname[n] = '\0'; 10627c478bd9Sstevel@tonic-gate 10637c478bd9Sstevel@tonic-gate if (count_symlinks(dirpath, rname, &n) < 0) { 10647c478bd9Sstevel@tonic-gate return; 10657c478bd9Sstevel@tonic-gate } 10667c478bd9Sstevel@tonic-gate 10677c478bd9Sstevel@tonic-gate if (n == 1) { 10687c478bd9Sstevel@tonic-gate (void) strcat(dirpath, rname); 10697c478bd9Sstevel@tonic-gate error = unlink(dirpath); 10707c478bd9Sstevel@tonic-gate if (debug >= 2) { 10717c478bd9Sstevel@tonic-gate if (error < 0) { 10727c478bd9Sstevel@tonic-gate (void) printf( 1073bbaa8b60SDan Kruchinin "remove_name: can't " 1074bbaa8b60SDan Kruchinin "unlink %s\n", 10757c478bd9Sstevel@tonic-gate dirpath); 10767c478bd9Sstevel@tonic-gate } else { 10777c478bd9Sstevel@tonic-gate (void) printf( 1078bbaa8b60SDan Kruchinin "remove_name: unlinked ", 1079bbaa8b60SDan Kruchinin "%s\n", dirpath); 10807c478bd9Sstevel@tonic-gate } 10817c478bd9Sstevel@tonic-gate } 10827c478bd9Sstevel@tonic-gate } 10837c478bd9Sstevel@tonic-gate } else { 10847c478bd9Sstevel@tonic-gate /* 10857c478bd9Sstevel@tonic-gate * Policy: if we can't read the symlink, leave it 10867c478bd9Sstevel@tonic-gate * here for analysis by the system administrator. 10877c478bd9Sstevel@tonic-gate */ 10887c478bd9Sstevel@tonic-gate syslog(LOG_ERR, 10897c478bd9Sstevel@tonic-gate "statd: can't read link %s: %m\n", path); 10907c478bd9Sstevel@tonic-gate } 10917c478bd9Sstevel@tonic-gate } 10927c478bd9Sstevel@tonic-gate 10937c478bd9Sstevel@tonic-gate /* 10947c478bd9Sstevel@tonic-gate * If it's a regular file, we can assume all symlinks and the 10957c478bd9Sstevel@tonic-gate * files to which they refer have been processed already - just 10967c478bd9Sstevel@tonic-gate * fall through to here to remove it. 10977c478bd9Sstevel@tonic-gate */ 10987c478bd9Sstevel@tonic-gate delete_file(path); 10997c478bd9Sstevel@tonic-gate } 11007c478bd9Sstevel@tonic-gate 11017c478bd9Sstevel@tonic-gate /* 11027c478bd9Sstevel@tonic-gate * Count the number of symlinks in `dir' which point to `name' (also in dir). 11037c478bd9Sstevel@tonic-gate * Passes back symlink count in `count'. 11047c478bd9Sstevel@tonic-gate * Returns 0 for success, < 0 for failure. 11057c478bd9Sstevel@tonic-gate */ 11067c478bd9Sstevel@tonic-gate static int 11077c478bd9Sstevel@tonic-gate count_symlinks(char *dir, char *name, int *count) 11087c478bd9Sstevel@tonic-gate { 11097c478bd9Sstevel@tonic-gate int cnt = 0; 11107c478bd9Sstevel@tonic-gate int n; 11117c478bd9Sstevel@tonic-gate DIR *dp; 11124bc0a2efScasper struct dirent *dirp; 11137c478bd9Sstevel@tonic-gate char lpath[MAXPATHLEN]; 11147c478bd9Sstevel@tonic-gate char rname[MAXNAMELEN + 1]; /* +1 for term NULL */ 11157c478bd9Sstevel@tonic-gate 1116*98573c19SMarcel Telka if ((dp = opendir(dir)) == NULL) { 11177c478bd9Sstevel@tonic-gate syslog(LOG_ERR, "count_symlinks: open %s dir, error %m\n", 11187c478bd9Sstevel@tonic-gate dir); 11197c478bd9Sstevel@tonic-gate return (-1); 11207c478bd9Sstevel@tonic-gate } 11217c478bd9Sstevel@tonic-gate 11224bc0a2efScasper while ((dirp = readdir(dp)) != NULL) { 11237c478bd9Sstevel@tonic-gate if (strcmp(dirp->d_name, ".") == 0 || 11247c478bd9Sstevel@tonic-gate strcmp(dirp->d_name, "..") == 0) { 11257c478bd9Sstevel@tonic-gate continue; 11267c478bd9Sstevel@tonic-gate } 11277c478bd9Sstevel@tonic-gate 11287c478bd9Sstevel@tonic-gate (void) sprintf(lpath, "%s%s", dir, dirp->d_name); 11297c478bd9Sstevel@tonic-gate if (is_symlink(lpath)) { 11307c478bd9Sstevel@tonic-gate /* 11317c478bd9Sstevel@tonic-gate * Fetch the name of the file the symlink refers to. 11327c478bd9Sstevel@tonic-gate */ 11337c478bd9Sstevel@tonic-gate n = readlink(lpath, rname, MAXNAMELEN); 11347c478bd9Sstevel@tonic-gate if (n <= 0) { 11357c478bd9Sstevel@tonic-gate if (debug >= 2) { 11367c478bd9Sstevel@tonic-gate (void) printf( 1137bbaa8b60SDan Kruchinin "count_symlinks: can't read link " 1138bbaa8b60SDan Kruchinin "%s\n", lpath); 11397c478bd9Sstevel@tonic-gate } 11407c478bd9Sstevel@tonic-gate continue; 11417c478bd9Sstevel@tonic-gate } 11427c478bd9Sstevel@tonic-gate rname[n] = '\0'; 11437c478bd9Sstevel@tonic-gate 11447c478bd9Sstevel@tonic-gate /* 11457c478bd9Sstevel@tonic-gate * If `rname' matches `name', bump the count. There 11467c478bd9Sstevel@tonic-gate * may well be multiple symlinks to the same name, so 11477c478bd9Sstevel@tonic-gate * we must continue to process the entire directory. 11487c478bd9Sstevel@tonic-gate */ 11497c478bd9Sstevel@tonic-gate if (strcmp(rname, name) == 0) { 11507c478bd9Sstevel@tonic-gate cnt++; 11517c478bd9Sstevel@tonic-gate } 11527c478bd9Sstevel@tonic-gate } 11537c478bd9Sstevel@tonic-gate } 11547c478bd9Sstevel@tonic-gate 11557c478bd9Sstevel@tonic-gate (void) closedir(dp); 11567c478bd9Sstevel@tonic-gate 11577c478bd9Sstevel@tonic-gate if (debug) { 11587c478bd9Sstevel@tonic-gate (void) printf("count_symlinks: found %d symlinks\n", cnt); 11597c478bd9Sstevel@tonic-gate } 11607c478bd9Sstevel@tonic-gate *count = cnt; 11617c478bd9Sstevel@tonic-gate return (0); 11627c478bd9Sstevel@tonic-gate } 11637c478bd9Sstevel@tonic-gate 11647c478bd9Sstevel@tonic-gate /* 11657c478bd9Sstevel@tonic-gate * Manage the cache of hostnames. An entry for each host that has recently 1166*98573c19SMarcel Telka * locked a file is kept. There is an in-ram table (record_table) and an empty 11677c478bd9Sstevel@tonic-gate * file in the file system name space (/var/statmon/sm/<name>). This 11687c478bd9Sstevel@tonic-gate * routine adds (deletes) the name to (from) the in-ram table and the entry 11697c478bd9Sstevel@tonic-gate * to (from) the file system name space. 11707c478bd9Sstevel@tonic-gate * 11717c478bd9Sstevel@tonic-gate * If op == 1 then the name is added to the queue otherwise the name is 11727c478bd9Sstevel@tonic-gate * deleted. 11737c478bd9Sstevel@tonic-gate */ 11747c478bd9Sstevel@tonic-gate void 1175*98573c19SMarcel Telka record_name(char *name, int op) 11767c478bd9Sstevel@tonic-gate { 11777c478bd9Sstevel@tonic-gate name_entry *nl; 11787c478bd9Sstevel@tonic-gate int i; 11797c478bd9Sstevel@tonic-gate char path[MAXPATHLEN+MAXNAMELEN+SM_MAXPATHLEN]; 11807c478bd9Sstevel@tonic-gate name_entry **record_q; 11817c478bd9Sstevel@tonic-gate unsigned int hash; 11827c478bd9Sstevel@tonic-gate 11837c478bd9Sstevel@tonic-gate /* 11847c478bd9Sstevel@tonic-gate * These names are supposed to be just host names, not paths or 11857c478bd9Sstevel@tonic-gate * other arbitrary files. 11867c478bd9Sstevel@tonic-gate * manipulating the empty pathname unlinks CURRENT, 11877c478bd9Sstevel@tonic-gate * manipulating files with '/' would allow you to create and unlink 11887c478bd9Sstevel@tonic-gate * files all over the system; LOG_AUTH, it's a security thing. 11897c478bd9Sstevel@tonic-gate * Don't remove the directories . and .. 11907c478bd9Sstevel@tonic-gate */ 11917c478bd9Sstevel@tonic-gate if (name == NULL) 11927c478bd9Sstevel@tonic-gate return; 11937c478bd9Sstevel@tonic-gate 11947c478bd9Sstevel@tonic-gate if (name[0] == '\0' || strchr(name, '/') != NULL || 11957c478bd9Sstevel@tonic-gate strcmp(name, ".") == 0 || strcmp(name, "..") == 0) { 11967c478bd9Sstevel@tonic-gate syslog(LOG_ERR|LOG_AUTH, "statd: attempt to %s \"%s/%s\"", 11977c478bd9Sstevel@tonic-gate op == 1 ? "create" : "remove", CURRENT, name); 11987c478bd9Sstevel@tonic-gate return; 11997c478bd9Sstevel@tonic-gate } 12007c478bd9Sstevel@tonic-gate 12017c478bd9Sstevel@tonic-gate SMHASH(name, hash); 12027c478bd9Sstevel@tonic-gate if (debug) { 12037c478bd9Sstevel@tonic-gate if (op == 1) 12047c478bd9Sstevel@tonic-gate (void) printf("inserting %s at hash %d,\n", 12057c478bd9Sstevel@tonic-gate name, hash); 12067c478bd9Sstevel@tonic-gate else 12077c478bd9Sstevel@tonic-gate (void) printf("deleting %s at hash %d\n", name, hash); 12087c478bd9Sstevel@tonic-gate pr_name(name, 1); 12097c478bd9Sstevel@tonic-gate } 12107c478bd9Sstevel@tonic-gate 12117c478bd9Sstevel@tonic-gate 12127c478bd9Sstevel@tonic-gate if (op == 1) { /* insert */ 12137c478bd9Sstevel@tonic-gate mutex_lock(&record_table[hash].lock); 12147c478bd9Sstevel@tonic-gate record_q = &record_table[hash].sm_rechdp; 1215*98573c19SMarcel Telka if ((nl = find_name(record_q, name)) == NULL) { 12167c478bd9Sstevel@tonic-gate 12177c478bd9Sstevel@tonic-gate int path_len; 12187c478bd9Sstevel@tonic-gate 12197c478bd9Sstevel@tonic-gate if ((nl = insert_name(record_q, name, 1)) != 12207c478bd9Sstevel@tonic-gate (name_entry *) NULL) 12217c478bd9Sstevel@tonic-gate nl->count++; 12227c478bd9Sstevel@tonic-gate mutex_unlock(&record_table[hash].lock); 12237c478bd9Sstevel@tonic-gate /* make an entry in current directory */ 12247c478bd9Sstevel@tonic-gate 12257c478bd9Sstevel@tonic-gate path_len = strlen(CURRENT) + strlen(name) + 2; 12267c478bd9Sstevel@tonic-gate if (path_len > MAXPATHLEN) { 12277c478bd9Sstevel@tonic-gate syslog(LOG_ERR, 12287c478bd9Sstevel@tonic-gate "statd: pathname too long: %s/%s\n", 12297c478bd9Sstevel@tonic-gate CURRENT, name); 12307c478bd9Sstevel@tonic-gate return; 12317c478bd9Sstevel@tonic-gate } 12327c478bd9Sstevel@tonic-gate (void) strcpy(path, CURRENT); 12337c478bd9Sstevel@tonic-gate (void) strcat(path, "/"); 12347c478bd9Sstevel@tonic-gate (void) strcat(path, name); 12357c478bd9Sstevel@tonic-gate (void) create_file(path); 12367c478bd9Sstevel@tonic-gate if (debug) { 12377c478bd9Sstevel@tonic-gate (void) printf("After insert_name\n"); 12387c478bd9Sstevel@tonic-gate pr_name(name, 1); 12397c478bd9Sstevel@tonic-gate } 12407c478bd9Sstevel@tonic-gate /* make an entry in alternate paths */ 12417c478bd9Sstevel@tonic-gate for (i = 0; i < pathix; i++) { 12427c478bd9Sstevel@tonic-gate path_len = strlen(path_name[i]) + 1243*98573c19SMarcel Telka strlen("/statmon/sm/") + strlen(name) + 1; 12447c478bd9Sstevel@tonic-gate 12457c478bd9Sstevel@tonic-gate if (path_len > MAXPATHLEN) { 1246*98573c19SMarcel Telka syslog(LOG_ERR, "statd: pathname too " 1247*98573c19SMarcel Telka "long: %s/statmon/sm/%s\n", 12487c478bd9Sstevel@tonic-gate path_name[i], name); 12497c478bd9Sstevel@tonic-gate continue; 12507c478bd9Sstevel@tonic-gate } 12517c478bd9Sstevel@tonic-gate (void) strcpy(path, path_name[i]); 12527c478bd9Sstevel@tonic-gate (void) strcat(path, "/statmon/sm/"); 12537c478bd9Sstevel@tonic-gate (void) strcat(path, name); 12547c478bd9Sstevel@tonic-gate (void) create_file(path); 12557c478bd9Sstevel@tonic-gate } 12567c478bd9Sstevel@tonic-gate return; 12577c478bd9Sstevel@tonic-gate } 12587c478bd9Sstevel@tonic-gate nl->count++; 12597c478bd9Sstevel@tonic-gate mutex_unlock(&record_table[hash].lock); 12607c478bd9Sstevel@tonic-gate 12617c478bd9Sstevel@tonic-gate } else { /* delete */ 12627c478bd9Sstevel@tonic-gate mutex_lock(&record_table[hash].lock); 12637c478bd9Sstevel@tonic-gate record_q = &record_table[hash].sm_rechdp; 1264*98573c19SMarcel Telka if ((nl = find_name(record_q, name)) == NULL) { 12657c478bd9Sstevel@tonic-gate mutex_unlock(&record_table[hash].lock); 12667c478bd9Sstevel@tonic-gate return; 12677c478bd9Sstevel@tonic-gate } 12687c478bd9Sstevel@tonic-gate nl->count--; 12697c478bd9Sstevel@tonic-gate if (nl->count == 0) { 12707c478bd9Sstevel@tonic-gate delete_name(record_q, name); 12717c478bd9Sstevel@tonic-gate mutex_unlock(&record_table[hash].lock); 12727c478bd9Sstevel@tonic-gate /* remove this entry from current directory */ 12737c478bd9Sstevel@tonic-gate remove_name(name, 0, 0); 12747c478bd9Sstevel@tonic-gate } else 12757c478bd9Sstevel@tonic-gate mutex_unlock(&record_table[hash].lock); 12767c478bd9Sstevel@tonic-gate if (debug) { 12777c478bd9Sstevel@tonic-gate (void) printf("After delete_name \n"); 12787c478bd9Sstevel@tonic-gate pr_name(name, 1); 12797c478bd9Sstevel@tonic-gate } 12807c478bd9Sstevel@tonic-gate } 12817c478bd9Sstevel@tonic-gate } 12827c478bd9Sstevel@tonic-gate 12837c478bd9Sstevel@tonic-gate /* 12847c478bd9Sstevel@tonic-gate * This routine adds a symlink in the form of an ASCII dotted quad 12857c478bd9Sstevel@tonic-gate * IP address that is linked to the name already recorded in the 12867c478bd9Sstevel@tonic-gate * filesystem name space by record_name(). Enough information is 12877c478bd9Sstevel@tonic-gate * (hopefully) provided to support other address types in the future. 12887c478bd9Sstevel@tonic-gate * The purpose of this is to cache enough information to contact 12897c478bd9Sstevel@tonic-gate * hosts in other domains during server crash recovery (see bugid 12907c478bd9Sstevel@tonic-gate * 1184192). 12917c478bd9Sstevel@tonic-gate * 12927c478bd9Sstevel@tonic-gate * The worst failure mode here is that the symlink is not made, and 12937c478bd9Sstevel@tonic-gate * statd falls back to the old buggy behavior. 12947c478bd9Sstevel@tonic-gate */ 12957c478bd9Sstevel@tonic-gate void 12967c478bd9Sstevel@tonic-gate record_addr(char *name, sa_family_t family, struct netobj *ah) 12977c478bd9Sstevel@tonic-gate { 12987c478bd9Sstevel@tonic-gate int i; 12997c478bd9Sstevel@tonic-gate int path_len; 13007c478bd9Sstevel@tonic-gate char *famstr; 13017c478bd9Sstevel@tonic-gate struct in_addr addr; 13027c478bd9Sstevel@tonic-gate char *addr6; 13037c478bd9Sstevel@tonic-gate char ascii_addr[MAXNAMELEN]; 13047c478bd9Sstevel@tonic-gate char path[MAXPATHLEN]; 13057c478bd9Sstevel@tonic-gate 13067c478bd9Sstevel@tonic-gate if (family == AF_INET) { 13077c478bd9Sstevel@tonic-gate if (ah->n_len != sizeof (struct in_addr)) 13087c478bd9Sstevel@tonic-gate return; 13097c478bd9Sstevel@tonic-gate addr = *(struct in_addr *)ah->n_bytes; 13107c478bd9Sstevel@tonic-gate } else if (family == AF_INET6) { 13117c478bd9Sstevel@tonic-gate if (ah->n_len != sizeof (struct in6_addr)) 13127c478bd9Sstevel@tonic-gate return; 13137c478bd9Sstevel@tonic-gate addr6 = (char *)ah->n_bytes; 13147c478bd9Sstevel@tonic-gate } else 13157c478bd9Sstevel@tonic-gate return; 13167c478bd9Sstevel@tonic-gate 13177c478bd9Sstevel@tonic-gate if (debug) { 13187c478bd9Sstevel@tonic-gate if (family == AF_INET) 13197c478bd9Sstevel@tonic-gate (void) printf("record_addr: addr= %x\n", addr.s_addr); 13207c478bd9Sstevel@tonic-gate else if (family == AF_INET6) 1321*98573c19SMarcel Telka (void) printf("record_addr: addr= %x\n", 13227c478bd9Sstevel@tonic-gate ((struct in6_addr *)addr6)->s6_addr); 13237c478bd9Sstevel@tonic-gate } 13247c478bd9Sstevel@tonic-gate 13257c478bd9Sstevel@tonic-gate if (family == AF_INET) { 13267c478bd9Sstevel@tonic-gate if (addr.s_addr == INADDR_ANY || 13272a9459bdSsangeeta ((addr.s_addr && 0xff000000) == 0)) { 13287c478bd9Sstevel@tonic-gate syslog(LOG_DEBUG, 13297c478bd9Sstevel@tonic-gate "record_addr: illegal IP address %x\n", 13307c478bd9Sstevel@tonic-gate addr.s_addr); 13317c478bd9Sstevel@tonic-gate return; 13327c478bd9Sstevel@tonic-gate } 13337c478bd9Sstevel@tonic-gate } 13347c478bd9Sstevel@tonic-gate 13357c478bd9Sstevel@tonic-gate /* convert address to ASCII */ 13367c478bd9Sstevel@tonic-gate famstr = family2string(family); 13377c478bd9Sstevel@tonic-gate if (famstr == NULL) { 13387c478bd9Sstevel@tonic-gate syslog(LOG_DEBUG, 13397c478bd9Sstevel@tonic-gate "record_addr: unsupported address family %d\n", 13407c478bd9Sstevel@tonic-gate family); 13417c478bd9Sstevel@tonic-gate return; 13427c478bd9Sstevel@tonic-gate } 13437c478bd9Sstevel@tonic-gate 13447c478bd9Sstevel@tonic-gate switch (family) { 13457c478bd9Sstevel@tonic-gate char abuf[INET6_ADDRSTRLEN]; 13467c478bd9Sstevel@tonic-gate case AF_INET: 13477c478bd9Sstevel@tonic-gate (void) sprintf(ascii_addr, "%s.%s", famstr, inet_ntoa(addr)); 13487c478bd9Sstevel@tonic-gate break; 13497c478bd9Sstevel@tonic-gate 13507c478bd9Sstevel@tonic-gate case AF_INET6: 1351*98573c19SMarcel Telka (void) sprintf(ascii_addr, "%s.%s", famstr, 13527c478bd9Sstevel@tonic-gate inet_ntop(family, addr6, abuf, sizeof (abuf))); 13537c478bd9Sstevel@tonic-gate break; 13547c478bd9Sstevel@tonic-gate 13557c478bd9Sstevel@tonic-gate default: 13567c478bd9Sstevel@tonic-gate if (debug) { 13577c478bd9Sstevel@tonic-gate (void) printf( 1358bbaa8b60SDan Kruchinin "record_addr: family2string supports unknown " 1359bbaa8b60SDan Kruchinin "family %d (%s)\n", family, famstr); 13607c478bd9Sstevel@tonic-gate } 13617c478bd9Sstevel@tonic-gate free(famstr); 13627c478bd9Sstevel@tonic-gate return; 13637c478bd9Sstevel@tonic-gate } 13647c478bd9Sstevel@tonic-gate 13657c478bd9Sstevel@tonic-gate if (debug) { 13667c478bd9Sstevel@tonic-gate (void) printf("record_addr: ascii_addr= %s\n", ascii_addr); 13677c478bd9Sstevel@tonic-gate } 13687c478bd9Sstevel@tonic-gate free(famstr); 13697c478bd9Sstevel@tonic-gate 13707c478bd9Sstevel@tonic-gate /* 13717c478bd9Sstevel@tonic-gate * Make the symlink in CURRENT. The `name' file should have 13727c478bd9Sstevel@tonic-gate * been created previously by record_name(). 13737c478bd9Sstevel@tonic-gate */ 13747c478bd9Sstevel@tonic-gate (void) create_symlink(CURRENT, name, ascii_addr); 13757c478bd9Sstevel@tonic-gate 13767c478bd9Sstevel@tonic-gate /* 13777c478bd9Sstevel@tonic-gate * Similarly for alternate paths. 13787c478bd9Sstevel@tonic-gate */ 13797c478bd9Sstevel@tonic-gate for (i = 0; i < pathix; i++) { 13807c478bd9Sstevel@tonic-gate path_len = strlen(path_name[i]) + 13817c478bd9Sstevel@tonic-gate strlen("/statmon/sm/") + 13827c478bd9Sstevel@tonic-gate strlen(name) + 1; 13837c478bd9Sstevel@tonic-gate 13847c478bd9Sstevel@tonic-gate if (path_len > MAXPATHLEN) { 13857c478bd9Sstevel@tonic-gate syslog(LOG_ERR, 13867c478bd9Sstevel@tonic-gate "statd: pathname too long: %s/statmon/sm/%s\n", 13877c478bd9Sstevel@tonic-gate path_name[i], name); 13887c478bd9Sstevel@tonic-gate continue; 13897c478bd9Sstevel@tonic-gate } 13907c478bd9Sstevel@tonic-gate (void) strcpy(path, path_name[i]); 13917c478bd9Sstevel@tonic-gate (void) strcat(path, "/statmon/sm"); 13927c478bd9Sstevel@tonic-gate (void) create_symlink(path, name, ascii_addr); 13937c478bd9Sstevel@tonic-gate } 13947c478bd9Sstevel@tonic-gate } 13957c478bd9Sstevel@tonic-gate 13967c478bd9Sstevel@tonic-gate /* 13977c478bd9Sstevel@tonic-gate * SM_CRASH - simulate a crash of statd. 13987c478bd9Sstevel@tonic-gate */ 13997c478bd9Sstevel@tonic-gate void 1400*98573c19SMarcel Telka sm_crash(void) 14017c478bd9Sstevel@tonic-gate { 14027c478bd9Sstevel@tonic-gate name_entry *nl, *next; 14037c478bd9Sstevel@tonic-gate mon_entry *nl_monp, *mon_next; 14047c478bd9Sstevel@tonic-gate int k; 14057c478bd9Sstevel@tonic-gate my_id *nl_idp; 14067c478bd9Sstevel@tonic-gate 14077c478bd9Sstevel@tonic-gate for (k = 0; k < MAX_HASHSIZE; k++) { 14087c478bd9Sstevel@tonic-gate mutex_lock(&mon_table[k].lock); 14097c478bd9Sstevel@tonic-gate if ((mon_next = mon_table[k].sm_monhdp) == 14107c478bd9Sstevel@tonic-gate (mon_entry *) NULL) { 14117c478bd9Sstevel@tonic-gate mutex_unlock(&mon_table[k].lock); 14127c478bd9Sstevel@tonic-gate continue; 14137c478bd9Sstevel@tonic-gate } else { 1414*98573c19SMarcel Telka while ((nl_monp = mon_next) != NULL) { 14157c478bd9Sstevel@tonic-gate mon_next = mon_next->nxt; 14167c478bd9Sstevel@tonic-gate nl_idp = &nl_monp->id.mon_id.my_id; 14177c478bd9Sstevel@tonic-gate free(nl_monp->id.mon_id.mon_name); 14187c478bd9Sstevel@tonic-gate free(nl_idp->my_name); 14197c478bd9Sstevel@tonic-gate free(nl_monp); 14207c478bd9Sstevel@tonic-gate } 1421*98573c19SMarcel Telka mon_table[k].sm_monhdp = NULL; 14227c478bd9Sstevel@tonic-gate } 14237c478bd9Sstevel@tonic-gate mutex_unlock(&mon_table[k].lock); 14247c478bd9Sstevel@tonic-gate } 14257c478bd9Sstevel@tonic-gate 14267c478bd9Sstevel@tonic-gate /* Clean up entries in record table */ 14277c478bd9Sstevel@tonic-gate for (k = 0; k < MAX_HASHSIZE; k++) { 14287c478bd9Sstevel@tonic-gate mutex_lock(&record_table[k].lock); 14297c478bd9Sstevel@tonic-gate if ((next = record_table[k].sm_rechdp) == 14307c478bd9Sstevel@tonic-gate (name_entry *) NULL) { 14317c478bd9Sstevel@tonic-gate mutex_unlock(&record_table[k].lock); 14327c478bd9Sstevel@tonic-gate continue; 14337c478bd9Sstevel@tonic-gate } else { 1434*98573c19SMarcel Telka while ((nl = next) != NULL) { 14357c478bd9Sstevel@tonic-gate next = next->nxt; 14367c478bd9Sstevel@tonic-gate free(nl->name); 14377c478bd9Sstevel@tonic-gate free(nl); 14387c478bd9Sstevel@tonic-gate } 1439*98573c19SMarcel Telka record_table[k].sm_rechdp = NULL; 14407c478bd9Sstevel@tonic-gate } 14417c478bd9Sstevel@tonic-gate mutex_unlock(&record_table[k].lock); 14427c478bd9Sstevel@tonic-gate } 14437c478bd9Sstevel@tonic-gate 14447c478bd9Sstevel@tonic-gate /* Clean up entries in recovery table */ 14457c478bd9Sstevel@tonic-gate mutex_lock(&recov_q.lock); 1446*98573c19SMarcel Telka if ((next = recov_q.sm_recovhdp) != NULL) { 1447*98573c19SMarcel Telka while ((nl = next) != NULL) { 14487c478bd9Sstevel@tonic-gate next = next->nxt; 14497c478bd9Sstevel@tonic-gate free(nl->name); 14507c478bd9Sstevel@tonic-gate free(nl); 14517c478bd9Sstevel@tonic-gate } 1452*98573c19SMarcel Telka recov_q.sm_recovhdp = NULL; 14537c478bd9Sstevel@tonic-gate } 14547c478bd9Sstevel@tonic-gate mutex_unlock(&recov_q.lock); 14557c478bd9Sstevel@tonic-gate statd_init(); 14567c478bd9Sstevel@tonic-gate } 14577c478bd9Sstevel@tonic-gate 14587c478bd9Sstevel@tonic-gate /* 14597c478bd9Sstevel@tonic-gate * Initialize the hash tables: mon_table, record_table, recov_q and 14607c478bd9Sstevel@tonic-gate * locks. 14617c478bd9Sstevel@tonic-gate */ 14627c478bd9Sstevel@tonic-gate void 1463*98573c19SMarcel Telka sm_inithash(void) 14647c478bd9Sstevel@tonic-gate { 14657c478bd9Sstevel@tonic-gate int k; 14667c478bd9Sstevel@tonic-gate 14677c478bd9Sstevel@tonic-gate if (debug) 14687c478bd9Sstevel@tonic-gate (void) printf("Initializing hash tables\n"); 14697c478bd9Sstevel@tonic-gate for (k = 0; k < MAX_HASHSIZE; k++) { 1470*98573c19SMarcel Telka mon_table[k].sm_monhdp = NULL; 1471*98573c19SMarcel Telka record_table[k].sm_rechdp = NULL; 14727c478bd9Sstevel@tonic-gate mutex_init(&mon_table[k].lock, USYNC_THREAD, NULL); 14737c478bd9Sstevel@tonic-gate mutex_init(&record_table[k].lock, USYNC_THREAD, NULL); 14747c478bd9Sstevel@tonic-gate } 14757c478bd9Sstevel@tonic-gate mutex_init(&recov_q.lock, USYNC_THREAD, NULL); 1476*98573c19SMarcel Telka recov_q.sm_recovhdp = NULL; 14777c478bd9Sstevel@tonic-gate 14787c478bd9Sstevel@tonic-gate } 14797c478bd9Sstevel@tonic-gate 14807c478bd9Sstevel@tonic-gate /* 14817c478bd9Sstevel@tonic-gate * Maps a socket address family to a name string, or NULL if the family 14827c478bd9Sstevel@tonic-gate * is not supported by statd. 14837c478bd9Sstevel@tonic-gate * Caller is responsible for freeing storage used by result string, if any. 14847c478bd9Sstevel@tonic-gate */ 14857c478bd9Sstevel@tonic-gate static char * 14867c478bd9Sstevel@tonic-gate family2string(sa_family_t family) 14877c478bd9Sstevel@tonic-gate { 14887c478bd9Sstevel@tonic-gate char *rc; 14897c478bd9Sstevel@tonic-gate 14907c478bd9Sstevel@tonic-gate switch (family) { 14917c478bd9Sstevel@tonic-gate case AF_INET: 14927c478bd9Sstevel@tonic-gate rc = strdup(SM_ADDR_IPV4); 14937c478bd9Sstevel@tonic-gate break; 14947c478bd9Sstevel@tonic-gate 14957c478bd9Sstevel@tonic-gate case AF_INET6: 14967c478bd9Sstevel@tonic-gate rc = strdup(SM_ADDR_IPV6); 14977c478bd9Sstevel@tonic-gate break; 14987c478bd9Sstevel@tonic-gate 14997c478bd9Sstevel@tonic-gate default: 15007c478bd9Sstevel@tonic-gate rc = NULL; 15017c478bd9Sstevel@tonic-gate break; 15027c478bd9Sstevel@tonic-gate } 15037c478bd9Sstevel@tonic-gate 15047c478bd9Sstevel@tonic-gate return (rc); 15057c478bd9Sstevel@tonic-gate } 15067c478bd9Sstevel@tonic-gate 15077c478bd9Sstevel@tonic-gate /* 15087c478bd9Sstevel@tonic-gate * Prints out list in record_table if flag is 1 otherwise 15097c478bd9Sstevel@tonic-gate * prints out each list in recov_q specified by name. 15107c478bd9Sstevel@tonic-gate */ 15117c478bd9Sstevel@tonic-gate static void 1512*98573c19SMarcel Telka pr_name(char *name, int flag) 15137c478bd9Sstevel@tonic-gate { 15147c478bd9Sstevel@tonic-gate name_entry *nl; 15157c478bd9Sstevel@tonic-gate unsigned int hash; 15167c478bd9Sstevel@tonic-gate 15177c478bd9Sstevel@tonic-gate if (!debug) 15187c478bd9Sstevel@tonic-gate return; 15197c478bd9Sstevel@tonic-gate if (flag) { 15207c478bd9Sstevel@tonic-gate SMHASH(name, hash); 15217c478bd9Sstevel@tonic-gate (void) printf("*****record_q: "); 15227c478bd9Sstevel@tonic-gate mutex_lock(&record_table[hash].lock); 15237c478bd9Sstevel@tonic-gate nl = record_table[hash].sm_rechdp; 1524*98573c19SMarcel Telka while (nl != NULL) { 15257c478bd9Sstevel@tonic-gate (void) printf("(%x), ", (int)nl); 15267c478bd9Sstevel@tonic-gate nl = nl->nxt; 15277c478bd9Sstevel@tonic-gate } 15287c478bd9Sstevel@tonic-gate mutex_unlock(&record_table[hash].lock); 15297c478bd9Sstevel@tonic-gate } else { 15307c478bd9Sstevel@tonic-gate (void) printf("*****recovery_q: "); 15317c478bd9Sstevel@tonic-gate mutex_lock(&recov_q.lock); 15327c478bd9Sstevel@tonic-gate nl = recov_q.sm_recovhdp; 1533*98573c19SMarcel Telka while (nl != NULL) { 15347c478bd9Sstevel@tonic-gate (void) printf("(%x), ", (int)nl); 15357c478bd9Sstevel@tonic-gate nl = nl->nxt; 15367c478bd9Sstevel@tonic-gate } 15377c478bd9Sstevel@tonic-gate mutex_unlock(&recov_q.lock); 15387c478bd9Sstevel@tonic-gate 15397c478bd9Sstevel@tonic-gate } 15407c478bd9Sstevel@tonic-gate (void) printf("\n"); 15417c478bd9Sstevel@tonic-gate } 1542