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 30 extern "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 58 struct 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 65 struct 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 72 struct 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 79 typedef 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 88 struct 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 99 typedef 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 108 typedef 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 116 typedef 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 124 struct 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 134 struct 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 142 struct 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 152 typedef 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 161 struct tnode { 162 void *node; 163 int flags; 164 struct di_devlink_handle *handle; 165 }; 166 167 struct di_devlink { 168 char *rel_path; 169 char *abs_path; 170 char *content; 171 int type; 172 }; 173 174 typedef 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 */ 182 typedef 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 */ 286 static struct di_devlink_handle *handle_alloc(const char *dev_dir, 287 uint_t flags); 288 static int cache_alloc(struct di_devlink_handle *hdp); 289 static int open_db(struct di_devlink_handle *hdp, int flags); 290 static int invalid_db(struct di_devlink_handle *hdp, size_t fsize, long pg_sz); 291 static int read_nodes(struct di_devlink_handle *hdp, cache_node_t *pcnp, 292 uint32_t nidx); 293 static int read_minors(struct di_devlink_handle *hdp, cache_node_t *pcnp, 294 uint32_t nidx); 295 static int read_links(struct di_devlink_handle *hdp, cache_minor_t *pcmp, 296 uint32_t nidx); 297 static int init_hdr(struct di_devlink_handle *hdp, long page_sz, 298 uint32_t *count); 299 static size_t size_db(struct di_devlink_handle *hdp, long page_sz, 300 uint32_t *count); 301 static size_t seg_size(struct di_devlink_handle *hdp, int seg); 302 303 static cache_node_t *node_insert(struct di_devlink_handle *hdp, 304 cache_node_t *pcnp, const char *path, int insert); 305 static 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); 308 static 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 311 static void minor_delete(di_devlink_handle_t hdp, cache_minor_t *cmnp); 312 static void link_delete(di_devlink_handle_t hdp, cache_link_t *clp); 313 314 static int write_nodes(struct di_devlink_handle *hdp, struct db_node *pdnp, 315 cache_node_t *cnp, uint32_t *next); 316 static int write_minors(struct di_devlink_handle *hdp, struct db_node *pdnp, 317 cache_minor_t *cmnp, uint32_t *next); 318 static int write_links(struct di_devlink_handle *hdp, struct db_minor *pdmp, 319 cache_link_t *clp, uint32_t *next); 320 static void rm_link_from_hash(struct di_devlink_handle *hdp, cache_link_t *clp); 321 static uint32_t write_string(struct di_devlink_handle *hdp, const char *str, 322 uint32_t *next); 323 static int close_db(struct di_devlink_handle *hdp); 324 static void cache_free(struct di_devlink_handle *hdp); 325 static void handle_free(struct di_devlink_handle **pp); 326 static void resolve_dangling_links(struct di_devlink_handle *hdp); 327 static void subtree_free(struct di_devlink_handle *hdp, cache_node_t **pp); 328 static void node_free(cache_node_t **pp); 329 static void minor_free(struct di_devlink_handle *hdp, cache_minor_t **pp); 330 static void link_free(cache_link_t **pp); 331 static void count_node(cache_node_t *cnp, uint32_t *count); 332 static void count_minor(cache_minor_t *mnp, uint32_t *count); 333 static void count_link(cache_link_t *clp, uint32_t *count); 334 static void count_string(const char *str, uint32_t *count); 335 static int visit_node(const char *path, void *arg); 336 static int walk_tree(char *cur, void *arg, 337 int (*node_callback)(const char *path, void *arg)); 338 static void *lookup_node(struct di_devlink_handle *hdp, char *path, 339 const int flags); 340 static cache_link_t *add_link(struct di_devlink_handle *hdp, const char *link, 341 const char *content, int primary); 342 343 static void *lookup_minor(struct di_devlink_handle *hdp, const char *minor_path, 344 const char *nodetype, const int flags); 345 static cache_link_t *link_hash(di_devlink_handle_t hdp, const char *link, 346 uint_t flags); 347 348 static void hash_insert(struct di_devlink_handle *hdp, cache_link_t *clp); 349 static uint_t hashfn(struct di_devlink_handle *hdp, const char *str); 350 static void get_db_path(struct di_devlink_handle *hdp, const char *fname, 351 char *buf, size_t blen); 352 353 static struct db_node *get_node(struct di_devlink_handle *hdp, uint32_t idx); 354 static struct db_node *set_node(struct di_devlink_handle *hdp, uint32_t idx); 355 356 static struct db_minor *get_minor(struct di_devlink_handle *hdp, uint32_t idx); 357 static struct db_minor *set_minor(struct di_devlink_handle *hdp, uint32_t idx); 358 359 static struct db_link *get_link(struct di_devlink_handle *hdp, uint32_t idx); 360 static struct db_link *set_link(struct di_devlink_handle *hdp, uint32_t idx); 361 362 static char *get_string(struct di_devlink_handle *hdp, uint32_t idx); 363 static char *set_string(struct di_devlink_handle *hdp, uint32_t idx); 364 365 static void *map_seg(struct di_devlink_handle *hdp, uint32_t idx, int prot, 366 db_seg_t seg); 367 368 static int walk_db(struct di_devlink_handle *hdp, link_desc_t *linkp); 369 static int walk_all_links(struct di_devlink_handle *hdp, link_desc_t *linkp); 370 static int walk_matching_links(struct di_devlink_handle *hdp, 371 link_desc_t *linkp); 372 static int visit_link(struct di_devlink_handle *hdp, link_desc_t *linkp, 373 struct di_devlink *vlp); 374 375 static void walk_cache_minor(di_devlink_handle_t hdp, const char *mpath, 376 link_desc_t *linkp); 377 static int walk_cache_links(di_devlink_handle_t hdp, cache_link_t *clp, 378 link_desc_t *linkp); 379 static void walk_all_cache(di_devlink_handle_t hdp, link_desc_t *linkp); 380 static int cache_dev_link(struct di_devlink_handle *hdp, void *data, 381 const char *link_path); 382 383 static int walk_dev(struct di_devlink_handle *hdp, link_desc_t *linkp); 384 static int recurse_dev(struct di_devlink_handle *hdp, recurse_t *rp); 385 static int do_recurse(const char *dir, struct di_devlink_handle *hdp, 386 recurse_t *rp, int *retp); 387 388 static int check_attr(uint32_t attr); 389 static int attr2type(uint32_t attr); 390 391 static int check_args(link_desc_t *linkp); 392 393 static void *get_last_node(struct di_devlink_handle *hdp, const char *path, 394 int flags); 395 static void *get_last_minor(struct di_devlink_handle *hdp, 396 const char *devfs_path, const char *minor_name, int flags); 397 static void set_last_minor(struct di_devlink_handle *hdp, cache_minor_t *cmnp, 398 int flags); 399 400 static int enter_db_lock(struct di_devlink_handle *hdp, const char *root_dir); 401 static void exit_db_lock(struct di_devlink_handle *hdp); 402 403 static char *minor_colon(const char *path); 404 static const char *rel_path(struct di_devlink_handle *hdp, const char *path); 405 static int link_flag(uint_t flags); 406 static int s_readlink(const char *link, char *buf, size_t blen); 407 static cache_minor_t *link2minor(struct di_devlink_handle *hdp, 408 cache_link_t *clp); 409 static int link_cmp(cache_link_t *clp, const char *content, int type); 410 static void delete_unused_nodes(di_devlink_handle_t hdp, cache_node_t *cnp); 411 static void delete_unused_minor(di_devlink_handle_t hdp, cache_minor_t *cmnp); 412 static int synchronize_db(di_devlink_handle_t hdp); 413 static void dprintf(debug_level_t msglevel, const char *fmt, ...); 414 static di_devlink_handle_t devlink_snapshot(const char *root_dir); 415 static int devlink_create(const char *root, const char *name, int dca_flags); 416 static int dca_init(const char *name, struct dca_off *dcp, int dca_flags); 417 static void exec_cmd(const char *root, struct dca_off *dcp); 418 static int do_exec(const char *path, char *const argv[]); 419 static int start_daemon(const char *root, int install); 420 static int daemon_call(const char *root, struct dca_off *dcp); 421 422 int is_minor_node(const char *contents, const char **mn_root); 423 char *s_realpath(const char *path, char *resolved_path); 424 425 #ifdef __cplusplus 426 } 427 #endif 428 429 #endif /* _DEVINFO_DEVLINK_H */ 430