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 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 22 * Use is subject to license terms. 23 */ 24 25 26#ifndef _DEVINFO_DEVLINK_H 27#define _DEVINFO_DEVLINK_H 28 29#ifdef __cplusplus 30extern "C" { 31#endif 32 33#define _POSIX_PTHREAD_SEMANTICS /* For readdir_r */ 34 35#include <stdio.h> 36#include <unistd.h> 37#include <fcntl.h> 38#include <string.h> 39#include <thread.h> 40#include <synch.h> 41#include <libdevinfo.h> 42#include <limits.h> 43#include <stdlib.h> 44#include <dirent.h> 45#include <regex.h> 46#include <errno.h> 47#include <stdarg.h> 48#include <sys/uio.h> 49#include <sys/types.h> 50#include <sys/stat.h> 51#include <sys/time.h> 52#include <sys/mman.h> 53#include <sys/wait.h> 54#include <door.h> 55#include <signal.h> 56#include <sys/statvfs.h> 57 58struct db_link { 59 uint32_t attr; /* primary or secondary */ 60 uint32_t path; /* link path */ 61 uint32_t content; /* link content */ 62 uint32_t sib; /* next link for same minor */ 63}; 64 65struct db_minor { 66 uint32_t name; /* minor name */ 67 uint32_t nodetype; /* minor node type */ 68 uint32_t sib; /* next minor for same node */ 69 uint32_t link; /* next minor for same node */ 70}; 71 72struct db_node { 73 uint32_t path; /* node path */ 74 uint32_t sib; /* node's sibling */ 75 uint32_t child; /* first child for this node */ 76 uint32_t minor; /* first minor for node */ 77}; 78 79typedef enum db_seg { 80 DB_NODE = 0, 81 DB_MINOR, 82 DB_LINK, 83 DB_STR, 84 DB_TYPES, /* Number of non-header segments */ 85 DB_HEADER 86} db_seg_t; 87 88struct db_hdr { 89 uint32_t magic; /* Magic number */ 90 uint32_t vers; /* database format version */ 91 uint32_t root_idx; /* index for root node */ 92 uint32_t dngl_idx; /* head of DB dangling links */ 93 uint32_t page_sz; /* page size for mmap alignment */ 94 uint32_t update_count; /* updates since last /dev synch up */ 95 uint32_t nelems[DB_TYPES]; /* Number of elements of each type */ 96}; 97 98 99typedef struct cache_link { 100 char *path; /* link path */ 101 char *content; /* link content */ 102 uint_t attr; /* link attributes */ 103 struct cache_link *hash; /* next link on same hash chain */ 104 struct cache_link *sib; /* next link for same minor */ 105 struct cache_minor *minor; /* minor for this link */ 106} cache_link_t; 107 108typedef struct cache_minor { 109 char *name; /* minor name */ 110 char *nodetype; /* minor nodetype */ 111 struct cache_node *node; /* node for this minor */ 112 struct cache_minor *sib; /* next minor for same node */ 113 struct cache_link *link; /* first link pointing to minor */ 114} cache_minor_t; 115 116typedef struct cache_node { 117 char *path; /* path */ 118 struct cache_node *parent; /* node's parent */ 119 struct cache_node *sib; /* node's sibling */ 120 struct cache_node *child; /* first child for this node */ 121 struct cache_minor *minor; /* first minor for node */ 122} cache_node_t; 123 124struct cache { 125 uint_t flags; /* cache state */ 126 uint_t update_count; /* updates since /dev synchronization */ 127 uint_t hash_sz; /* number of hash chains */ 128 cache_link_t **hash; /* hash table */ 129 cache_node_t *root; /* root of cache tree */ 130 cache_link_t *dngl; /* list of dangling links */ 131 cache_minor_t *last_minor; /* last minor looked up */ 132}; 133 134struct db { 135 int db_fd; /* database file */ 136 uint_t flags; /* database open mode */ 137 struct db_hdr *hdr; /* DB header */ 138 int seg_prot[DB_TYPES]; /* protection for segments */ 139 caddr_t seg_base[DB_TYPES]; /* base address for segments */ 140}; 141 142struct di_devlink_handle { 143 char *dev_dir; /* <root-dir>/dev */ 144 char *db_dir; /* <root-dir>/etc/dev */ 145 uint_t flags; /* handle flags */ 146 uint_t error; /* records errors encountered */ 147 int lock_fd; /* lock file for updates */ 148 struct cache cache; 149 struct db db; 150}; 151 152typedef struct link_desc { 153 regex_t *regp; 154 const char *minor_path; 155 uint_t flags; 156 void *arg; 157 int (*fcn)(di_devlink_t, void *); 158 int retval; 159} link_desc_t; 160 161struct tnode { 162 void *node; 163 int flags; 164 struct di_devlink_handle *handle; 165}; 166 167struct di_devlink { 168 char *rel_path; 169 char *abs_path; 170 char *content; 171 int type; 172}; 173 174typedef struct recurse { 175 void *data; 176 int (*fcn)(struct di_devlink_handle *, void *, const char *); 177} recurse_t; 178 179/* 180 * Debug levels currently defined. 181 */ 182typedef enum { 183 DBG_ERR = 1, 184 DBG_LCK, 185 DBG_INFO, 186 DBG_STEP, 187 DBG_ALL 188} debug_level_t; 189 190 191#define DB_MAGIC 0xBAC2ACAB 192#define DB_FILE ".devlink_db" 193#define DB_TMP ".devlink_db_tmp" 194#define DB_LOCK ".devlink_db_lock" 195#define DB_PERMS (S_IRUSR | S_IRGRP | S_IROTH | S_IWUSR) 196#define DB_LOCK_PERMS DB_PERMS 197#define DB_VERSION 1 198 199#define DB_NIL 0 200 201#define DEV "/dev" 202#define ETCDEV "/etc/dev" 203#define DEVICES_SUFFIX "ices" 204 205#define HDR_LEN sizeof (struct db_hdr) 206 207#define AVG_CHAIN_SIZE 20 /* Average number of links per chain */ 208#define MIN_HASH_SIZE 1024 /* Min number of chains in hash table */ 209#define MAX_UPDATE_INTERVAL 5 /* Max DB writes before synching with /dev */ 210#define MAX_LOCK_RETRY 5 /* Max attempts at locking the update lock */ 211 212/* 213 * Various flags private to the implementation 214 */ 215#define A_PRIMARY 0x0001U 216#define A_SECONDARY 0x0002U 217#define A_LINK_TYPES 0x0003U /* Mask */ 218#define A_VALID 0x0004U 219 220#define TYPE_DB 0x0008U 221#define TYPE_CACHE 0x0010U 222#define CREATE_FLAG 0x0020U 223 224#define INSERT_HEAD 0x0040U 225#define INSERT_TAIL 0x0080U 226#define OPEN_RDWR 0x0100U 227#define OPEN_RDONLY 0x0200U 228#define OPEN_FLAGS 0x0300U /* Mask */ 229#define UNLINK_FROM_HASH 0x0400U 230 231#define SET_VALID_ATTR(a) ((a) |= A_VALID) 232#define CLR_VALID_ATTR(a) ((a) &= ~A_VALID) 233#define GET_VALID_ATTR(a) ((a) & A_VALID) 234 235#define SET_DB_ERR(h) ((h)->error = 1) 236#define DB_ERR(h) ((h)->error) 237 238#define LOOKUP_DB(f) ((f) & TYPE_DB) 239#define LOOKUP_CACHE(f) ((f) & TYPE_CACHE) 240#define CREATE_ELEM(f) ((f) & CREATE_FLAG) 241 242#define IS_RDWR(f) (((f) & OPEN_FLAGS) == OPEN_RDWR) 243#define IS_RDONLY(f) (((f) & OPEN_FLAGS) == OPEN_RDONLY) 244 245#define HDL_RDWR(h) (((h)->flags & OPEN_FLAGS) == OPEN_RDWR) 246#define HDL_RDONLY(h) (((h)->flags & OPEN_FLAGS) == OPEN_RDONLY) 247 248#define CACHE(h) (&(h)->cache) 249#define CACHE_ROOT(h) (CACHE(h)->root) 250#define CACHE_HASH(h, i) (CACHE(h)->hash[i]) 251#define CACHE_LAST(h) (CACHE(h)->last_minor) 252#define CACHE_EMPTY(h) (CACHE(h)->root == NULL && CACHE(h)->dngl == NULL) 253 254#define DB(h) (&(h)->db) 255#define DB_HDR(h) (DB(h)->hdr) 256#define DB_NUM(h, t) (DB_HDR(h)->nelems[t]) 257#define DB_SEG(h, t) (DB(h)->seg_base[t]) 258#define DB_SEG_PROT(h, t) (DB(h)->seg_prot[t]) 259 260#define DB_OPEN(h) (DB_HDR(h) != NULL) 261#define DB_RDWR(h) ((DB(h)->flags & OPEN_FLAGS) == OPEN_RDWR) 262#define DB_RDONLY(h) ((DB(h)->flags & OPEN_FLAGS) == OPEN_RDONLY) 263 264#define DB_EMPTY(h) (DB_HDR(h)->root_idx == DB_NIL && \ 265 DB_HDR(h)->dngl_idx == DB_NIL) 266 267#define TYPE_NONE(f) (((f) & DI_LINK_TYPES) == 0) 268#define TYPE_PRI(f) (((f) & DI_LINK_TYPES) == DI_PRIMARY_LINK) 269#define TYPE_SEC(f) (((f) & DI_LINK_TYPES) == DI_SECONDARY_LINK) 270#define LINK_TYPE(f) ((f) & DI_LINK_TYPES) 271#define VALID_TYPE(f) (TYPE_NONE(f) || TYPE_PRI(f) || TYPE_SEC(f)) 272 273#define VALID_STR(h, i, s) ((i) + strlen(s) + 1 <= DB_HDR(h)->nelems[DB_STR]) 274#define VALID_INDEX(h, t, i) ((i) < DB_HDR(h)->nelems[t]) 275 276/* 277 * Environment variables used by DEBUG version of code. 278 */ 279#define SKIP_DB "DEBUG_SKIP_DB" 280#define SKIP_LAST_CACHE "DEBUG_SKIP_LAST_CACHE" 281#define ALT_DB_DIR "DEBUG_ALT_DB_DIR" 282 283/* 284 * Function prototypes 285 */ 286static struct di_devlink_handle *handle_alloc(const char *dev_dir, 287 uint_t flags); 288static int cache_alloc(struct di_devlink_handle *hdp); 289static int open_db(struct di_devlink_handle *hdp, int flags); 290static int invalid_db(struct di_devlink_handle *hdp, size_t fsize, long pg_sz); 291static int read_nodes(struct di_devlink_handle *hdp, cache_node_t *pcnp, 292 uint32_t nidx); 293static int read_minors(struct di_devlink_handle *hdp, cache_node_t *pcnp, 294 uint32_t nidx); 295static int read_links(struct di_devlink_handle *hdp, cache_minor_t *pcmp, 296 uint32_t nidx); 297static int init_hdr(struct di_devlink_handle *hdp, long page_sz, 298 uint32_t *count); 299static size_t size_db(struct di_devlink_handle *hdp, long page_sz, 300 uint32_t *count); 301static size_t seg_size(struct di_devlink_handle *hdp, int seg); 302 303static cache_node_t *node_insert(struct di_devlink_handle *hdp, 304 cache_node_t *pcnp, const char *path, int insert); 305static cache_minor_t *minor_insert(struct di_devlink_handle *hdp, 306 cache_node_t *pcnp, const char *name, const char *nodetype, 307 cache_minor_t **prev); 308static cache_link_t *link_insert(struct di_devlink_handle *hdp, 309 cache_minor_t *mnp, const char *path, const char *content, uint32_t attr); 310 311static void minor_delete(di_devlink_handle_t hdp, cache_minor_t *cmnp); 312static void link_delete(di_devlink_handle_t hdp, cache_link_t *clp); 313 314static int write_nodes(struct di_devlink_handle *hdp, struct db_node *pdnp, 315 cache_node_t *cnp, uint32_t *next); 316static int write_minors(struct di_devlink_handle *hdp, struct db_node *pdnp, 317 cache_minor_t *cmnp, uint32_t *next); 318static int write_links(struct di_devlink_handle *hdp, struct db_minor *pdmp, 319 cache_link_t *clp, uint32_t *next); 320static void rm_link_from_hash(struct di_devlink_handle *hdp, cache_link_t *clp); 321static uint32_t write_string(struct di_devlink_handle *hdp, const char *str, 322 uint32_t *next); 323static int close_db(struct di_devlink_handle *hdp); 324static void cache_free(struct di_devlink_handle *hdp); 325static void handle_free(struct di_devlink_handle **pp); 326static void resolve_dangling_links(struct di_devlink_handle *hdp); 327static void subtree_free(struct di_devlink_handle *hdp, cache_node_t **pp); 328static void node_free(cache_node_t **pp); 329static void minor_free(struct di_devlink_handle *hdp, cache_minor_t **pp); 330static void link_free(cache_link_t **pp); 331static void count_node(cache_node_t *cnp, uint32_t *count); 332static void count_minor(cache_minor_t *mnp, uint32_t *count); 333static void count_link(cache_link_t *clp, uint32_t *count); 334static void count_string(const char *str, uint32_t *count); 335static int visit_node(const char *path, void *arg); 336static int walk_tree(char *cur, void *arg, 337 int (*node_callback)(const char *path, void *arg)); 338static void *lookup_node(struct di_devlink_handle *hdp, char *path, 339 const int flags); 340static cache_link_t *add_link(struct di_devlink_handle *hdp, const char *link, 341 const char *content, int primary); 342 343static void *lookup_minor(struct di_devlink_handle *hdp, const char *minor_path, 344 const char *nodetype, const int flags); 345static cache_link_t *link_hash(di_devlink_handle_t hdp, const char *link, 346 uint_t flags); 347 348static void hash_insert(struct di_devlink_handle *hdp, cache_link_t *clp); 349static uint_t hashfn(struct di_devlink_handle *hdp, const char *str); 350static void get_db_path(struct di_devlink_handle *hdp, const char *fname, 351 char *buf, size_t blen); 352 353static struct db_node *get_node(struct di_devlink_handle *hdp, uint32_t idx); 354static struct db_node *set_node(struct di_devlink_handle *hdp, uint32_t idx); 355 356static struct db_minor *get_minor(struct di_devlink_handle *hdp, uint32_t idx); 357static struct db_minor *set_minor(struct di_devlink_handle *hdp, uint32_t idx); 358 359static struct db_link *get_link(struct di_devlink_handle *hdp, uint32_t idx); 360static struct db_link *set_link(struct di_devlink_handle *hdp, uint32_t idx); 361 362static char *get_string(struct di_devlink_handle *hdp, uint32_t idx); 363static char *set_string(struct di_devlink_handle *hdp, uint32_t idx); 364 365static void *map_seg(struct di_devlink_handle *hdp, uint32_t idx, int prot, 366 db_seg_t seg); 367 368static int walk_db(struct di_devlink_handle *hdp, link_desc_t *linkp); 369static int walk_all_links(struct di_devlink_handle *hdp, link_desc_t *linkp); 370static int walk_matching_links(struct di_devlink_handle *hdp, 371 link_desc_t *linkp); 372static int visit_link(struct di_devlink_handle *hdp, link_desc_t *linkp, 373 struct di_devlink *vlp); 374 375static void walk_cache_minor(di_devlink_handle_t hdp, const char *mpath, 376 link_desc_t *linkp); 377static int walk_cache_links(di_devlink_handle_t hdp, cache_link_t *clp, 378 link_desc_t *linkp); 379static void walk_all_cache(di_devlink_handle_t hdp, link_desc_t *linkp); 380static int cache_dev_link(struct di_devlink_handle *hdp, void *data, 381 const char *link_path); 382 383static int walk_dev(struct di_devlink_handle *hdp, link_desc_t *linkp); 384static int recurse_dev(struct di_devlink_handle *hdp, recurse_t *rp); 385static int do_recurse(const char *dir, struct di_devlink_handle *hdp, 386 recurse_t *rp, int *retp); 387 388static int check_attr(uint32_t attr); 389static int attr2type(uint32_t attr); 390 391static int check_args(link_desc_t *linkp); 392 393static void *get_last_node(struct di_devlink_handle *hdp, const char *path, 394 int flags); 395static void *get_last_minor(struct di_devlink_handle *hdp, 396 const char *devfs_path, const char *minor_name, int flags); 397static void set_last_minor(struct di_devlink_handle *hdp, cache_minor_t *cmnp, 398 int flags); 399 400static int enter_db_lock(struct di_devlink_handle *hdp, const char *root_dir); 401static void exit_db_lock(struct di_devlink_handle *hdp); 402 403static char *minor_colon(const char *path); 404static const char *rel_path(struct di_devlink_handle *hdp, const char *path); 405static int link_flag(uint_t flags); 406static int s_readlink(const char *link, char *buf, size_t blen); 407static cache_minor_t *link2minor(struct di_devlink_handle *hdp, 408 cache_link_t *clp); 409static int link_cmp(cache_link_t *clp, const char *content, int type); 410static void delete_unused_nodes(di_devlink_handle_t hdp, cache_node_t *cnp); 411static void delete_unused_minor(di_devlink_handle_t hdp, cache_minor_t *cmnp); 412static int synchronize_db(di_devlink_handle_t hdp); 413static void dprintf(debug_level_t msglevel, const char *fmt, ...); 414static di_devlink_handle_t devlink_snapshot(const char *root_dir); 415static int devlink_create(const char *root, const char *name, int dca_flags); 416static int dca_init(const char *name, struct dca_off *dcp, int dca_flags); 417static void exec_cmd(const char *root, struct dca_off *dcp); 418static int do_exec(const char *path, char *const argv[]); 419static int start_daemon(const char *root, int install); 420static int daemon_call(const char *root, struct dca_off *dcp); 421 422int is_minor_node(const char *contents, const char **mn_root); 423char *s_realpath(const char *path, char *resolved_path); 424 425#ifdef __cplusplus 426} 427#endif 428 429#endif /* _DEVINFO_DEVLINK_H */ 430