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