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 (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 /*
  22  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
  23  * Use is subject to license terms.
  24  */
  25 
  26 #ifndef _CFG_IMPL_H
  27 #define _CFG_IMPL_H
  28 
  29 #ifdef __cplusplus
  30 extern "C" {
  31 #endif
  32 
  33 #define MAX_CFG         16      /* Max. number of lines in /etc/dscfg_format */
  34 
  35 #define CFG_MAX_KEY     256
  36 #define CFG_MAX_BUF     1024
  37 #define CFG_BLOCK_SIZE  512
  38 #define CFG_VTOC_SIZE   16
  39 #define CFG_VTOC_SKIP   CFG_VTOC_SIZE * CFG_BLOCK_SIZE
  40 
  41 /*
  42  * Parser and file handling routines for Configuration parser.
  43  *
  44  *      General layout on disk
  45  *
  46  *      header                          cfgheader_t
  47  *      parser configuration            tag.field1.field2\n
  48  *      configuration data copy1        freeform strings
  49  *      configuration data copy2        freeform strings
  50  *
  51  * Strings in freeform fields are seperated by whitespace.
  52  * End of entry seperated by null.
  53  */
  54 
  55 struct lookup {
  56         char            l_word[CFG_MAX_KEY];
  57         int             l_value;
  58         struct lookup   *l_next;
  59 };
  60 
  61 struct parser {
  62         struct lookup   tag;
  63         struct lookup   *fld;
  64         struct parser   *next;
  65 };
  66 
  67 
  68 /*
  69  * cfglist description
  70  *
  71  *                         ________
  72  *                        |        | the header has (with other things) an array
  73  *                        | header | of h_cfg[n].l_size entries. index 4
  74  *  disk layout           |        | contains cfp->cf_head->h_cfg[4].l_size.
  75  *                        |________|
  76  *        cfgfile-mapped->|        |
  77  * CFG_DEFAULT_PARSE_SIZE | parser | cache_hint.device.wrthru.nordcache.cnode
  78  *                        |        |
  79  *                        |________|
  80  * cfp->cf_head->h_ccopy1>|        |
  81  *   CFG_DEFAULT_SSIZE    |  data  | null terminated strings grouped together
  82  *                        | copy 1 | in order of cfglist offset. ie data at
  83  *                        |________| offset 0 is from h_cfgs[0].l_entry
  84  * cfp->cf_head->h_ccopy2>|        |
  85  *   CFG_DEFAULT_SSIZE    |  data  |
  86  *                        | copy 2 | same as above, used for two stage commit
  87  *                        |________|
  88  * cfp->cf_head->h_sizes1>|        | here is where lists of sizes go for each
  89  *   CFG_DEFAULT_PSIZE    | sizes  | cfglist. each array is preceded by the num
  90  *                        | copy 1 | of entries. |5|120|130|140|103|125|10|25 is
  91  *                        |________| a list with 5 entries 120,130,140,103,125
  92  * cfp->cf_head->h_sizes2>|        | these numbers are used to rebuild l_nentry
  93  *   CFG_DEFAULT_PSIZE    |  sizes | and l_esiz fields in h_cfg[n]
  94  *                        | copy 2 | this list is done as a two stage commit
  95  *                        |________|
  96  *
  97  *
  98  *
  99  * Data is read into cfp->cf_head->h_ccopy1 and cfp->cf_head->h_ccopy2
 100  * along with thier corresponding size metadata in cfp->cf_head->h_sizes1
 101  * and cfp->cf_head->h_sizes2. This infomation is used to rebuild the
 102  * cfglist structures seen below. The data in the cfglist structure is then
 103  * the ONLY valid data. Additions and/or deletions to the database is done
 104  * by moving around the cfglists and doing the right things with the size
 105  * arrays, the actual entries, total list sizes, the total of all the sizes of
 106  * all the cfglists and memory allocation. After addition/deletions are done,
 107  * and cfg_close is called, all of the lists are placed back into h_cparse
 108  * (which is really h_ccopy1 or h_ccopy2) the persistent lists are placed
 109  * into h_sizes (which is really h_sizes1 or h_sizes2).
 110  * A copy of each cfglist[n].l_size is kept in the header
 111  * (cfgheader->cfgsizes[n]).
 112  *
 113  *
 114  *
 115  *
 116  *                h_cfgs        h_cfgs[3]
 117  *    head        |-[0]-   /|-l_name  == sndr
 118  *      |-       /|-[1]-  / |-l_entry == host dev bmap host..ip sync '\0' ...
 119  * file |-      / |-[2]- /  |-l_esiz[0..l_nentry - 1] == [130, 132, 135, 133,..]
 120  *   |--|---------|-[3]---- |-l_enabled[0..l_nentry - 1] == [1,0,0,1,1]
 121  *      |-      \ |-[4]- \  |-l_nentry == 5
 122  *      |-       \|-[5]-  \ |-l_index == 3
 123  *                |-[n]-   \|-l_free == 50537
 124  *                          |-l_size == 663 (130 + 132 + 135 + 133 + 133)
 125  *
 126  *
 127  *
 128  * l_name - is set when the parser is read.
 129  *      It is the first tag of a line of parser text.
 130  * l_entry - is a pointer to the beginning of the null terminated string
 131  *      list that belongs to the cfglist tagged with l_name.
 132  * l_esiz - is a list of sizes of the strings contained in l_entry.
 133  *      l_esiz[0] tells the size of the string at l_entry[0].
 134  *      l_esiz[n] is the size of the string that begins
 135  *      at l_entry + l_esiz[0] + l_esiz[1]..+ l_esize[n - 1]
 136  * l_enabled - is a list of ones and zeros telling if this entry is alive
 137  *      in the kernel. indexing is the same as l_esiz. (not implemented)
 138  * l_index - is the index of the parser tree that corresponds to l_name
 139  *      and is set when the parser tree is built
 140  * l_free - is how memory is managed. Memory is allocated on a
 141  *      DEFAULT_ENTRY_SIZE boundry.
 142  *      the size of the balance of available memory at the end of l_entry
 143  *      is kept here. when this number is lower than the string we need to add,
 144  *      another block of memory is allocated for l_entry and the balance of
 145  *      the size is added to l_free.
 146  * l_size - is size of this list. It is the summation of l_esiz[0..n]
 147  *
 148  */
 149 
 150 typedef struct cfglist {
 151         char    *l_name;        /* name of list sndr, ii.. */
 152         char    *l_entry;       /* start of list */
 153         int     *l_esiz;        /* array of sizes of entries */
 154         int     l_nentry;       /* number of entries */
 155         int     l_index;        /* index in relation to parser position */
 156         uint_t  l_free;         /* num of characters available */
 157         int     l_size;         /* size of list */
 158 } cfglist_t;
 159 
 160 /* note: this does not imply DEFAULT_NENTRIES * DEFAULT_ENTRY_SIZE */
 161 #define DEFAULT_NENTRIES        100 /* value for l_esiz sizes array */
 162 #define DEFAULT_ENTRY_SIZE      (50 * CFG_MAX_BUF) /* 50K for each l_entry */
 163 
 164 
 165 typedef struct cfgheader {
 166         int32_t h_magic;
 167         int     h_state;        /* State flag see below */
 168         time_t  h_stamp;        /* time stamp of last update */
 169         long    h_lock;         /* lock for update */
 170         long    h_size;         /* total file size */
 171         int     h_parseoff;     /* parser config offset */
 172         int     h_parsesize;    /* parser config size */
 173         char    *h_cparse;      /* start of configuration  */
 174         int     h_csize;        /* size of config section */
 175         int     h_acsize;       /* size of alternate config section */
 176         int     *h_sizes;       /* sizes of lists */
 177         int     h_psize;        /* size of persistent section */
 178         int     h_apsize;       /* size of alternate persistent section */
 179         char    *h_ccopy1;      /* base of config section 1 */
 180         char    *h_ccopy2;      /* base of config section 2 */
 181         int     *h_sizes1;      /* sizes of lists on disk 1 */
 182         int     *h_sizes2;      /* sizes of lists on disk 2 */
 183         int     h_seq1;         /* Sequenece number copy 1 both sections */
 184         int     h_seq2;         /* Sequenece number copy 2 both sections */
 185         char    h_ncfgs;        /* number of cfgs */
 186         cfglist_t *h_cfgs;      /* start of cfg lists */
 187         int     h_cfgsizes[MAX_CFG];    /* Sizes of configs */
 188 } cfgheader_t;
 189 
 190 #define CFG_HDR_GOOD    0x1
 191 #define CFG_HDR_INVALID 0x2
 192 #define CFG_HDR_RDLOCK  0x4
 193 #define CFG_HDR_WRLOCK  0x8
 194 
 195 struct cfg_io_s;                /* forward reference */
 196 typedef struct cfp {
 197         int     cf_fd;          /* file descriptor */
 198         int     cf_flag;        /* flags - see below */
 199         long    cf_size;        /* size of file in fbas */
 200         int     cf_lock;        /* lock file descriptor */
 201         char    *cf_mapped;     /* mapped location via mmap */
 202         char    *cf_name;       /* file name */
 203         cfgheader_t *cf_head;   /* header */
 204         struct cfg_io_s *cf_pp; /* i/o provider */
 205 } cfp_t;
 206 
 207 typedef struct cfgfile {
 208         void    *cf_node;       /* node filter */
 209         cfp_t   cf[2];          /* local & optional cluster file */
 210 } CFGFILE;
 211 
 212 typedef struct cfg_io_s {
 213         struct cfg_io_s *next;                  /* Link to next module */
 214         char    *name;                          /* name of provider */
 215         cfp_t   *(*open)(cfp_t *, char *);      /* Open device */
 216         void    (*close)(cfp_t *);              /* Close device */
 217         int     (*seek)(cfp_t *, int, int);     /* Seek */
 218         int     (*read)(cfp_t *, void *, int);  /* read */
 219         int     (*write)(cfp_t *, void *, int); /* write */
 220         char    *(*readcf)(cfp_t *, char *, int, int); /* Read mem config */
 221         int     (*addcf)(cfp_t *, char *, int); /* add to mem config */
 222         int     (*remcf)(cfp_t *, int, int);    /* remove an entry */
 223         int     (*replacecf)(cfp_t *, char *, int, int); /* replace entry */
 224 } cfg_io_t;
 225 
 226 #define CFG_FILE        0x1     /* database is in a regular file */
 227 #define CFG_NOREWIND    0x4     /* don't rewind for each get_string */
 228 #define CFG_NOWRVTOC    0x8     /* sector starts in vtoc land, skip it */
 229 #define CFG_RDONLY      0x10    /* database is read only */
 230 
 231 /*
 232  * constants
 233  */
 234 #define CFG_RDEV_LOCKFILE       "/var/tmp/.dscfg.lck"
 235 #define CFG_NEW_MAGIC           0x4d414749              /* MAGI */
 236 #define CFG_DEFAULT_PARSE_SIZE  (16 * 1024)
 237 #define CFG_DEFAULT_SSIZE       (2 * 1024 * 1024)
 238 #define CFG_DEFAULT_PSIZE       (512 * 1024)
 239 #define CFG_DEFAULT_OLDSIZE     (96 * 1024)
 240 #define CFG_CONFIG_SIZE         (CFG_DEFAULT_PARSE_SIZE + \
 241                                 (2 * CFG_DEFAULT_SSIZE) + \
 242                                 (2 * CFG_DEFAULT_PSIZE))
 243 #ifdef  __cplusplus
 244 }
 245 #endif
 246 
 247 #endif  /* _CFG_IMPL_H */