1 /*
   2  * CDDL HEADER START
   3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License, Version 1.0 only
   6  * (the "License").  You may not use this file except in compliance
   7  * with the License.
   8  *
   9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  10  * or http://www.opensolaris.org/os/licensing.
  11  * See the License for the specific language governing permissions
  12  * and limitations under the License.
  13  *
  14  * When distributing Covered Code, include this CDDL HEADER in each
  15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  16  * If applicable, add the following below this CDDL HEADER, with the
  17  * fields enclosed by brackets "[]" replaced with your own identifying
  18  * information: Portions Copyright [yyyy] [name of copyright owner]
  19  *
  20  * CDDL HEADER END
  21  */
  22 /*
  23  * Copyright (c) 2000 by Sun Microsystems, Inc.
  24  * All rights reserved.
  25  */
  26 
  27 #ifndef DSVCD_CONTAINER_H
  28 #define DSVCD_CONTAINER_H
  29 
  30 #pragma ident   "%Z%%M% %I%     %E% SMI"
  31 
  32 #include <sys/types.h>
  33 #include <synch.h>
  34 
  35 #include "dsvclockd.h"
  36 
  37 /*
  38  * Container-related data structures, functions and constants.  See
  39  * comments in container.c for a description of how to use the exported
  40  * functions.
  41  */
  42 
  43 #ifdef  __cplusplus
  44 extern "C" {
  45 #endif
  46 
  47 /*
  48  * Number of seconds to wait for container lockholders to relinquish all
  49  * locks on a given container (when it's being destroyed).
  50  */
  51 #define CN_DESTROY_WAIT 60
  52 
  53 /*
  54  * Describes a thread waiting to access a given container; exactly one per
  55  * waiting thread.
  56  */
  57 typedef struct dsvcd_waitlist {
  58         struct dsvcd_waitlist   *wl_next;       /* next waiter in list */
  59         struct dsvcd_waitlist   *wl_prev;       /* prev waiter in list */
  60         cond_t                  wl_cv;          /* our condition variable */
  61         dsvcd_locktype_t        wl_locktype;    /* type of lock we want */
  62 } dsvcd_waitlist_t;
  63 
  64 /*
  65  * States for the host lock state machine.  The state machine is a simple
  66  * cycle of UNLOCKED->PENDING->{RD,WR}LOCKED->UNLOCKED->...
  67  */
  68 enum cn_hlockstate { CN_HUNLOCKED, CN_HPENDING, CN_HRDLOCKED, CN_HWRLOCKED };
  69 
  70 /*
  71  * Describes a given container within a datastore.  There is at most one of
  72  * these per datastore container (there may be none if there are no current
  73  * consumers of a given container within a datastore).  If there is more
  74  * than one open handle to a given container (through multiple calls to
  75  * open_d?()) there will still only be one dsvcd_container_t for that
  76  * container.  This object is used to synchronize access to an underlying
  77  * container through use of its custom reader/writer lock (it can't use the
  78  * rwlock_t's built into Solaris because we need locks that do not care if
  79  * the unlocking thread is the same as the locking thread).  It also
  80  * contains other per-container information like the container id.
  81  */
  82 typedef struct dsvcd_container {
  83         char                    *cn_id;         /* container's id */
  84         boolean_t               cn_crosshost;   /* synchronize across hosts */
  85         boolean_t               cn_closing;     /* container is going away */
  86         mutex_t                 cn_lock;        /* protects preceding fields */
  87 
  88         dsvcd_waitlist_t        *cn_whead;      /* head of wait list */
  89         dsvcd_waitlist_t        *cn_wtail;      /* tail of wait list */
  90         int                     cn_nholds;      /* num readers (-1 == writer) */
  91         mutex_t                 cn_nholds_lock; /* for nholds and waitlist */
  92 
  93         int                     cn_hlockfd;     /* host lock file descriptor */
  94         int                     cn_hlockcount;  /* current # of host locks */
  95         enum cn_hlockstate      cn_hlockstate;  /* host lock state */
  96         cond_t                  cn_hlockcv;     /* host lock condvar */
  97         mutex_t                 cn_hlock_lock;  /* mutex for cn_hlock* */
  98 
  99         /*
 100          * These fields are used to keep metadata state regarding the
 101          * container and are actually maintained by the containing
 102          * datastore, not the container.
 103          */
 104         uint_t                  cn_nout;        /* number checked out */
 105         time_t                  cn_lastrel;     /* last released */
 106         uint32_t                cn_idhash;      /* hash before modulation */
 107         struct dsvcd_container  *cn_next;       /* hash chain next */
 108         struct dsvcd_container  *cn_prev;       /* hash chain prev */
 109 } dsvcd_container_t;
 110 
 111 extern dsvcd_container_t        *cn_create(const char *, boolean_t);
 112 extern void                     cn_destroy(dsvcd_container_t *);
 113 extern int                      cn_rdlock(dsvcd_container_t *, boolean_t);
 114 extern int                      cn_wrlock(dsvcd_container_t *, boolean_t);
 115 extern int                      cn_unlock(dsvcd_container_t *);
 116 extern dsvcd_locktype_t         cn_locktype(dsvcd_container_t *);
 117 
 118 #ifdef  __cplusplus
 119 }
 120 #endif
 121 
 122 #endif  /* DSVCD_CONTAINER_H */