/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2007 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
#include <unistd.h>
#include <syslog.h>
#include <thread.h>
#include <synch.h>
#include <strings.h>
#include <ndbm.h>
#include "../ypsym.h"
#include "../ypdefs.h"
#include "shim.h"
/*
* These routines provide mutual exclusion between ypserv and ypxfr.
* Mutual exclusion is needed so that ypxfr doesn't try to rename
* dbm files while ypserv is trying to open them. After ypserv has
* opened a dbm file, it is safe to rename it because ypserv still
* has access to the file through its file descriptor.
*/
struct lockarray {
};
/*
* Cross-process robust mutex locks.
* Provide synchronization between YP processes
* by implementing an exclusive locking mechanism
* via a memory-mapped file.
*/
static int lockfile;
/*
* Hash functions, used for by the locking mechanism.
*
* - hash() is the front-end function that gets called.
* - get_map_id() returns a unique int value per map.
* It is used in N2L mode only.
* It is called by hash() in N2L mode.
*/
int
{
/*
* Local references to hash table for map lists
* and to max number of maps
*/
int max_map;
/* initializes map_list_p & max_map */
/* found */
}
}
", giving max_map value (%d)",
/*
* max_map does not match any map id, hence
* will not trigger any lock collision
* with existing maps.
* Needed for yp regular locking mechanism.
*/
return (max_map);
}
int
hash(char *s)
{
unsigned int n = 0;
int i;
char *map_name = s;
for (i = 1; *s; i += 10, s++) {
n += i * (*s);
}
n %= MAXHASH;
if (yptol_mode & yptol_newlock) {
return (get_map_id(map_name, n));
} else {
return (n);
}
}
bool
{
int ebusy_cnt = 0;
/*
* Initialize cross-process locks in memory-mapped file.
*/
USYNC_PROCESS | LOCK_ROBUST, 0)) {
ebusy_cnt++;
} else {
"init_locks_mem():mutex_init():error=%d",
rc);
return (FALSE);
}
}
}
/*
* EBUSY for all locks OK, it means another process
* has already initialized locks.
*/
"%s inconsistent. Remove and restart NIS (YP).", LOCKFILE);
return (FALSE);
}
return (TRUE);
}
bool
{
/*
* Locking file initialization algorithm, with recovery mechanism.
* This mechanism has been devised to ensure proper creation
* of a memory-mapped lock file containing mutexes for robust,
* inter-process communication.
* File name is /var/run/yp_maplock (LOCKFILE). It might or might
* not exist.
*
* Algorithm:
* Try to open the file. If file doesn't exist, or size is too small,
* mutexes in it.
* If file exists and size is at least large enough, assume it's a
* good file, and m-map the lock structure directly to it.
*
* Recovery from inconsistent state is easy - simply delete the file
* and restart NIS (YP).
*/
if (lockfile != -1) {
if (write_cnt < 0) {
"write(%s) => errno=%d",
} else {
"write(%s) => %d!=%d: wrong number of bytes written.",
sizeof (buff));
}
return (FALSE);
}
}
} else {
return (FALSE);
}
} else {
return (FALSE);
}
} else {
return (FALSE);
}
/*
* File exists with correct size, is open, and we're holding
* the file lock.
*/
if (shmlockarray == MAP_FAILED) {
return (FALSE);
}
/*
* If we wrote zeroes to the file, we also need to initialize
* the mutex locks.
*/
if (init_locks_mem() == FALSE) {
"remove(%s) => errno=%d: Please delete file.",
}
return (FALSE);
}
}
"lockf(%s,F_ULOCK) => errno=%d",
return (FALSE);
}
return (TRUE);
} else {
return (FALSE);
}
}
/*
* FUNCTION : lock_map()
*
* DESCRIPTION: Front end to the lock routine taking map name as argument.
*
* GIVEN : Map name.
*
* RETURNS : Same as lock_core
*/
int
{
int hashval;
}
/*
* FUNCTION : lock_core()
*
* DESCRIPTION: The core map locking function
*
* GIVEN : Map hash value
*
* RETURNS : 0 = Failure
* 1 = Success
*/
int
{
int rc;
/*
* Robust, cross-process lock implementation
*/
while (rc != 0) {
switch (rc) {
case EOWNERDEAD:
/*
* Previous lock owner died, resetting lock
* to recover from error.
*/
if (rc != 0) {
"mutex_consistent(): error=%d", rc);
return (0);
}
if (rc != 0) {
"mutex_unlock(): error=%d", rc);
return (0);
}
break;
default:
/*
* Unrecoverable problem - nothing to do
* but exit YP and delete lock file.
*/
"mutex_lock(): error=%d", rc);
"remove(%s) => errno=%d: Please delete file.",
}
return (0);
}
}
/* Success */
return (1);
}
/*
* FUNCTION : unlock_map()
*
* DESCRIPTION: Front end to the unlock routine taking map name as argument.
*
* GIVEN : Map name.
*
* RETURNS : Same as unlock_core
*/
int
{
int hashval;
return (unlock_core(hashval));
}
/*
* FUNCTION : unlock_core()
*
* DESCRIPTION: The core map locking function
*
* GIVEN : Map hash value
*
* RETURNS : 0 = Failure
* 1 = Success
*/
int
{
int rc;
if (rc != 0) {
"mutex_unlock(): error=%d", rc);
"remove(%s) => errno=%d: Please delete file.",
}
return (0);
}
/* Success */
return (1);
}