1
0
Files
irix-657m-src/eoe/cmd/sun/rpc.lockd/hash.c
2022-09-29 17:59:04 +03:00

339 lines
7.7 KiB
C

#if 0
static char sccsid[] = "@(#)hash.c 1.3 91/06/25 NFSSRC4.1 Copyr 1986 Sun Micro";
#endif
/*
* Copyright (c) 1988 by Sun Microsystems, Inc.
*/
/*
* hash.c
* rotuines handle insertion, deletion of hashed monitor, file entries
*/
#include <stdio.h>
#include <assert.h>
#include "prot_lock.h"
extern int debug;
typedef struct lm_vnode cache_me;
#define MAX_HASHSIZE 100
static cache_me *table_me[MAX_HASHSIZE];
#define isempty(l) (l == (struct reclocklist*)l->rnext)
static void
print_reclist(struct reclocklist *rptr, char *str)
{
struct reclock *tptr;
int first = 1;
if (rptr == NULL)
return;
FOREACH_RECLIST(rptr, tptr) {
if (first) {
printf("%s\n", str);
first = 0;
}
printf(
"server %s, %sblk %s, type %d, base %d, len %d, pid %d\n",
tptr->lck.server_name,
tptr->block ? "" : "non",
tptr->exclusive ? "write" : "read",
tptr->lck.lox.type,
tptr->lck.lox.base,
tptr->lck.lox.length,
tptr->lck.lox.pid);
}
}
void
print_monlocks(void)
{
cache_me *ptr;
int i;
printf("Monitored locks: ");
for (i = 0; i < MAX_HASHSIZE; i++) {
if ((ptr = table_me[i]) != NULL) {
print_reclist(&ptr->exclusive, "Exclusive");
print_reclist(&ptr->shared, "Shared");
print_reclist(&ptr->pending, "Pending");
}
}
putchar('\n');
}
/*
* find_me returns the cached entry;
* it returns NULL if not found;
*/
struct lm_vnode *
find_me(svr)
char *svr;
{
cache_me *cp;
if (debug > 2)
printf("find_me: %s\n", svr);
cp = table_me[hash(svr)];
while ( cp != NULL) {
if (debug > 2)
printf(" > %s\n", cp->server_name);
if (strcasecmp(cp->server_name, svr) == 0) {
/* found */
return (cp);
}
cp = cp->next;
}
return (NULL);
}
/*
* insert_me() -- add monitor entry to the hash table
*/
void
insert_me(mp)
struct lm_vnode *mp;
{
int h;
h = hash(mp->server_name);
mp->next = table_me[h];
table_me[h] = mp;
}
/*
* add_req_to_me() -- add lock request req to the monitor list
*/
void
add_req_to_me(req, status)
struct reclock *req;
{
struct lm_vnode *me;
if (debug > 1)
printf("enter add_req_to_me (reclock %x status %d) ...\n",
req, status);
/* find the monitor entry for this server, it should be found */
/* as the entry is created before the lock request is sent out*/
/* to the server. */
if ((me = find_me(req->lck.server_name)) == NULL) {
if (debug)
printf("rpc.lockd: monitor entry not found for \"%s\", request is not monitored.\n", req->lck.server_name);
return;
}
switch (status) {
/* add request to the appropriate list */
/* exclusive or shared if the request */
/* is granted */
case nlm_granted: if (req->exclusive) {
merge_lock(req, &me->exclusive);
/* if an upgrade lock, we rm the */
/* the lock from the shared list */
lm_unlock_region(req, &me->shared);
} else {
merge_lock(req, &me->shared);
/* if downgrade of lock, we rm the */
/* lock from the exclusive list */
lm_unlock_region(req, &me->exclusive);
}
if (debug) {
print_reclist(&me->exclusive, "Exclusive");
print_reclist(&me->shared, "Shared");
}
break;
/* if request is queued at server, add */
/* it to the pending list */
case nlm_blocked: add_req_to_list(req, &me->pending);
break;
}
}
/*
* upgrade_req_in_me() -- will move the lock request req that's in the
* monitor's pending list to exclusive/shared list
*/
void
upgrade_req_in_me(req)
struct reclock *req;
{
struct lm_vnode *me;
if (debug)
printf("enter upgrade_req_in_me (req %x%s) ...\n",
req, req->exclusive ? " excl" : "");
/* find the monitor entry for this server, it should be found */
/* as the entry is created before the lock request is sent out*/
/* to the server. */
if ((me = find_me(req->lck.server_name)) == NULL) {
if (debug)
printf(
"mon entry not found for \"%s\", request is not monitored.\n",
req->lck.server_name);
return;
}
/* remove the request from the pending list */
(void) del_req_from_list(&req->lck.lox, &me->pending);
/* add the request to the exclusive/shared list */
if (req->exclusive)
merge_lock(req, &me->exclusive);
else
merge_lock(req, &me->shared);
}
/*
* remove_req_in_me() -- will remove the lock request req from the monitor's
* pending, exclusive or shared list.
* del_req() is used to free the memory of the lock
* request.
*/
void
remove_req_in_me(req)
struct reclock *req;
{
struct lm_vnode *me;
if (debug > 1)
printf("enter remove_req_in_me (reclock %x) ...\n", req);
/* find the monitor entry for this server, it should be found */
/* as the entry is created before the lock request is sent out*/
/* to the server. */
if ((me = find_me(req->lck.server_name)) == NULL) {
if (debug)
printf("monitor entry not found for \"%s\", request is not monitored.\n", req->lck.server_name);
return;
}
/* since we don't know which of the monitor list this request reside */
/* we'll try pending, and then exclusive or shared list. */
/* the memory of this lock request req will be freed by del_req() */
if (del_req(req, &me->pending))
return;
lm_unlock_region(req, &me->exclusive);
lm_unlock_region(req, &me->shared);
}
/*
* add_req_to_list() -- to add a lock request req to the monitor list listp
*/
void
add_req_to_list(req, list)
struct reclock *req;
struct reclocklist *list;
{
struct reclock *tmp_p;
if (debug)
printf("enter add_req_to_list (req %x list %x %s) ...\n",
req, list, isempty(list) ? "empty" : "");
/* make sure the request is not in the list already, this is possible */
/* due to retransmissions. */
FOREACH_RECLIST(list, tmp_p) {
if (debug)
printf(" %x\n", tmp_p);
if ((tmp_p == req) ||
(same_lock(req, &(tmp_p->lck.lox)) &&
obj_cmp(&(req->lck.fh), &(tmp_p->lck.fh)))) {
req->rel = 1; /* duplicate, can be freed */
return;
}
}
req->rprev = (struct reclock *)list;
req->rnext = list->rnext;
list->rnext->rprev = req;
list->rnext = req;
}
void
rm_req(struct reclock *req)
{
req->rprev->rnext = req->rnext;
req->rnext->rprev = req->rprev;
req->rnext = req->rprev = NULL;
}
/*
* del_req_from_list() -- will remove the request of the data lock l from the
* doubly linked list listp
* similar to del_req() except it doesn't free reclock
* + arg is data_lock instead of reclock.
* if the req is not found, return NULL; else return the
* reclock.
*/
struct reclock *
del_req_from_list(l, list)
struct data_lock *l;
struct reclocklist *list;
{
struct reclock *tmp_p;
if (debug)
printf("enter del_req_from_list (lox %x list %x %s) ...\n",
l, list, isempty(list) ? "empty" : "");
FOREACH_RECLIST(list, tmp_p) {
if (debug)
printf(" %x: %x\n", tmp_p, &tmp_p->lck.lox);
if (&tmp_p->lck.lox == l) {
rm_req(tmp_p);
return (tmp_p);
}
}
return (NULL);
}
/*
* del_req() -- similar to del_req_from_list() in that it will remove the
* request req from the linked list listp. difference in that
* del_req() will free the memory of req.
* difference is arg is reclock instead of data lock.
* if the req is not found, return FALSE; else TRUE.
*/
bool_t
del_req(req, list)
struct reclock *req;
struct reclocklist *list;
{
struct reclock *tmp_p;
if (debug)
printf("enter del_req (reclock %x list %x %s) ...\n",
req, list, isempty(list) ? "empty" : "");
FOREACH_RECLIST(list, tmp_p) {
if (debug)
printf(" ? %x", tmp_p);
if ((WITHIN(&(tmp_p->lck.lox), &(req->lck.lox)) ||
same_bound(&(req->lck.lox), &(tmp_p->lck.lox))) &&
SAMEOWNER(&(req->lck.lox), &(tmp_p->lck.lox)) &&
obj_cmp(&(req->lck.fh), &(tmp_p->lck.fh))) {
tmp_p->rel = 1;
rm_req(tmp_p);
release_reclock(tmp_p);
if (debug)
printf(" deleted\n");
return (TRUE);
}
if (debug)
printf("\n");
}
return (FALSE);
}