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