diff options
| author | vikram <none@none> | 2006-10-02 14:44:57 -0700 |
|---|---|---|
| committer | vikram <none@none> | 2006-10-02 14:44:57 -0700 |
| commit | aa646b9dad0e03cc01e7fe5bea924c5267e2df75 (patch) | |
| tree | 384911d82a5925b707e1d508b09595c38f609130 /usr | |
| parent | f67ca41a3fe371a8ac34045eb45b3c5449ee601c (diff) | |
| download | illumos-joyent-aa646b9dad0e03cc01e7fe5bea924c5267e2df75.tar.gz | |
6462748 devfsadm link removal does not provide full interpose support
Diffstat (limited to 'usr')
| -rw-r--r-- | usr/src/cmd/devfsadm/devfsadm.c | 150 | ||||
| -rw-r--r-- | usr/src/cmd/devfsadm/devfsadm.h | 24 | ||||
| -rw-r--r-- | usr/src/cmd/devfsadm/devfsadm_impl.h | 15 | ||||
| -rw-r--r-- | usr/src/cmd/devfsadm/lofi_link.c | 27 |
4 files changed, 199 insertions, 17 deletions
diff --git a/usr/src/cmd/devfsadm/devfsadm.c b/usr/src/cmd/devfsadm/devfsadm.c index c1ffa5e1aa..1053dd8776 100644 --- a/usr/src/cmd/devfsadm/devfsadm.c +++ b/usr/src/cmd/devfsadm/devfsadm.c @@ -207,6 +207,10 @@ static int login_dev_enable = FALSE; /* Global to use devinfo snapshot cache */ static int use_snapshot_cache = FALSE; +/* Global for no-further-processing hash */ +static item_t **nfp_hash; +static mutex_t nfp_mutex = DEFAULTMUTEX; + /* * Packaged directories - not removed even when empty. * The dirs must be listed in canonical form @@ -391,6 +395,7 @@ update_drvconf(major_t major) major); } + static void load_dev_acl() { @@ -2037,7 +2042,7 @@ static void load_module(char *mname, char *cdir) { _devfsadm_create_reg_t *create_reg; - _devfsadm_remove_reg_t *remove_reg; + _devfsadm_remove_reg_V1_t *remove_reg; create_list_t *create_list_element; create_list_t **create_list_next; remove_list_t *remove_list_element; @@ -2047,6 +2052,7 @@ load_module(char *mname, char *cdir) char *dlerrstr; void *dlhandle; module_t *module; + int flags; int n; int i; @@ -2079,7 +2085,7 @@ load_module(char *mname, char *cdir) } /* dlsym the _devfsadm_remove_reg structure */ - if (NULL == (remove_reg = (_devfsadm_remove_reg_t *) + if (NULL == (remove_reg = (_devfsadm_remove_reg_V1_t *) dlsym(dlhandle, _DEVFSADM_REMOVE_REG))) { vprint(MODLOAD_MID, "dlsym(%s,\n\t%s): symbol not found\n", epath, _DEVFSADM_REMOVE_REG); @@ -2220,13 +2226,17 @@ load_module(char *mname, char *cdir) * put a ptr to each struct devfsadm_remove on "remove_head" * list sorted by interpose_lvl. */ + flags = 0; if (remove_reg != NULL) { + if (remove_reg->version < DEVFSADM_V1) + flags |= RM_NOINTERPOSE; for (i = 0; i < remove_reg->count; i++) { remove_list_element = (remove_list_t *) s_malloc(sizeof (remove_list_t)); remove_list_element->remove = &(remove_reg->tblp[i]); + remove_list_element->remove->flags |= flags; remove_list_element->modptr = module; for (remove_list_next = &(remove_head); @@ -4004,6 +4014,9 @@ pre_and_post_cleanup(int flags) rd.data = (void *)&cleanup_data; cleanup_data.flags = flags; + (void) mutex_lock(&nfp_mutex); + nfphash_create(); + for (rm = remove_head; rm != NULL; rm = rm->next) { if ((flags & rm->remove->flags) == flags) { cleanup_data.rm = rm; @@ -4020,6 +4033,8 @@ pre_and_post_cleanup(int flags) } } } + nfphash_destroy(); + (void) mutex_unlock(&nfp_mutex); } /* @@ -4044,7 +4059,7 @@ pre_and_post_cleanup(int flags) * */ static int -clean_ok(devfsadm_remove_t *remove) +clean_ok(devfsadm_remove_V1_t *remove) { int i; @@ -4103,6 +4118,7 @@ hot_cleanup(char *node_path, char *minor_name, char *ev_subclass, char rmlink[PATH_MAX + 1]; nvlist_t *nvl = NULL; int skip; + int ret; /* * dev links can go away as part of hot cleanup. @@ -4120,6 +4136,9 @@ hot_cleanup(char *node_path, char *minor_name, char *ev_subclass, vprint(REMOVE_MID, "%spath=%s\n", fcn, path); + (void) mutex_lock(&nfp_mutex); + nfphash_create(); + for (rm = remove_head; rm != NULL; rm = rm->next) { if ((RM_HOT & rm->remove->flags) == RM_HOT) { head = get_cached_links(rm->remove->dev_dirs_re); @@ -4137,6 +4156,14 @@ hot_cleanup(char *node_path, char *minor_name, char *ev_subclass, * the next valid link. */ head->nextlink = link->next; + + /* + * if devlink is in no-further-process hash, + * skip its remove + */ + if (nfphash_lookup(link->devlink) != NULL) + continue; + if (minor_name) skip = strcmp(link->contents, path); else @@ -4157,11 +4184,22 @@ hot_cleanup(char *node_path, char *minor_name, char *ev_subclass, */ (void) snprintf(rmlink, sizeof (rmlink), "%s", link->devlink); - (*(rm->remove->callback_fcn))(rmlink); + if (rm->remove->flags & RM_NOINTERPOSE) { + ((void (*)(char *)) + (rm->remove->callback_fcn))(rmlink); + } else { + ret = ((int (*)(char *)) + (rm->remove->callback_fcn))(rmlink); + if (ret == DEVFSADM_TERMINATE) + nfphash_insert(rmlink); + } } } } + nfphash_destroy(); + (void) mutex_unlock(&nfp_mutex); + /* update device allocation database */ if (system_labeled) { int ret = 0; @@ -4263,22 +4301,44 @@ static void matching_dev(char *devpath, void *data) { cleanup_data_t *cleanup_data = data; + int norm_len = strlen(dev_dir) + strlen("/"); + int ret; char *fcn = "matching_dev: "; vprint(RECURSEDEV_MID, "%sexamining devpath = '%s'\n", fcn, devpath); + /* + * If the link is in the no-further-process hash + * don't do any remove operation on it. + */ + if (nfphash_lookup(devpath + norm_len) != NULL) + return; + if (resolve_link(devpath, NULL, NULL, NULL, 1) == TRUE) { if (call_minor_init(cleanup_data->rm->modptr) == DEVFSADM_FAILURE) { return; } - devpath += strlen(dev_dir) + strlen("/"); + devpath += norm_len; vprint(RECURSEDEV_MID, "%scalling" " callback %s\n", fcn, devpath); - (*(cleanup_data->rm->remove->callback_fcn))(devpath); + if (cleanup_data->rm->remove->flags & RM_NOINTERPOSE) + ((void (*)(char *)) + (cleanup_data->rm->remove->callback_fcn))(devpath); + else { + ret = ((int (*)(char *)) + (cleanup_data->rm->remove->callback_fcn))(devpath); + if (ret == DEVFSADM_TERMINATE) { + /* + * We want no further remove processing for + * this link. Add it to the nfp_hash; + */ + nfphash_insert(devpath); + } + } } } @@ -8043,6 +8103,84 @@ is_blank(char *line) return (1); } +/* + * Functions to deal with the no-further-processing hash + */ + +static void +nfphash_create(void) +{ + assert(nfp_hash == NULL); + nfp_hash = s_zalloc(NFP_HASH_SZ * sizeof (item_t *)); +} + +static int +nfphash_fcn(char *key) +{ + int i; + uint64_t sum = 0; + + for (i = 0; key[i] != '\0'; i++) { + sum += (uchar_t)key[i]; + } + + return (sum % NFP_HASH_SZ); +} + +static item_t * +nfphash_lookup(char *key) +{ + int index; + item_t *ip; + + index = nfphash_fcn(key); + + assert(index >= 0); + + for (ip = nfp_hash[index]; ip; ip = ip->i_next) { + if (strcmp(ip->i_key, key) == 0) + return (ip); + } + + return (NULL); +} + +static void +nfphash_insert(char *key) +{ + item_t *ip; + int index; + + index = nfphash_fcn(key); + + assert(index >= 0); + + ip = s_zalloc(sizeof (item_t)); + ip->i_key = s_strdup(key); + + ip->i_next = nfp_hash[index]; + nfp_hash[index] = ip; +} + +static void +nfphash_destroy(void) +{ + int i; + item_t *ip; + + for (i = 0; i < NFP_HASH_SZ; i++) { + /*LINTED*/ + while (ip = nfp_hash[i]) { + nfp_hash[i] = ip->i_next; + free(ip->i_key); + free(ip); + } + } + + free(nfp_hash); + nfp_hash = NULL; +} + static int devname_kcall(int subcmd, void *args) { diff --git a/usr/src/cmd/devfsadm/devfsadm.h b/usr/src/cmd/devfsadm/devfsadm.h index 4688e6043c..ae6216eb89 100644 --- a/usr/src/cmd/devfsadm/devfsadm.h +++ b/usr/src/cmd/devfsadm/devfsadm.h @@ -55,6 +55,7 @@ extern "C" { #define ILEVEL_9 9 #define DEVFSADM_V0 0 +#define DEVFSADM_V1 1 #define DEVFSADM_CONTINUE 0 #define DEVFSADM_TERMINATE 1 @@ -66,6 +67,7 @@ extern "C" { #define RM_PRE 0x02 #define RM_POST 0x04 #define RM_ALWAYS 0x08 +#define RM_NOINTERPOSE 0x10 #define TYPE_EXACT 0x01 #define TYPE_RE 0x02 @@ -109,9 +111,17 @@ typedef struct devfsadm_remove { char *dev_dirs_re; /* dev dirs regex selector */ int flags; /* eg POST, PRE, HOT, ALWAYS */ int interpose_lvl; /* eg ILEVEL_0 .. ILEVEL_10 */ - void (*callback_fcn)(char *logical_link); + void (*callback_fcn)(char *); } devfsadm_remove_t; +typedef struct devfsadm_remove_V1 { + char *device_class; /* eg "disk", "tape", "display" */ + char *dev_dirs_re; /* dev dirs regex selector */ + int flags; /* eg POST, PRE, HOT, ALWAYS */ + int interpose_lvl; /* eg ILEVEL_0 .. ILEVEL_10 */ + int (*callback_fcn)(char *); +} devfsadm_remove_V1_t; + typedef struct _devfsadm_create_reg { uint_t version; uint_t count; /* number of node type registration */ @@ -126,6 +136,12 @@ typedef struct _devfsadm_remove_reg { devfsadm_remove_t *tblp; } _devfsadm_remove_reg_t; +typedef struct _devfsadm_remove_reg_V1 { + uint_t version; + uint_t count; /* number of node type registration */ + /* structures */ + devfsadm_remove_V1_t *tblp; +} _devfsadm_remove_reg_V1_t; /* * "flags" in the devfs_enumerate structure can take the following values. * These values specify the substring of devfs path to be used for @@ -167,6 +183,12 @@ typedef struct devfsadm_enumerate { (sizeof (tbl) / sizeof (devfsadm_remove_t)), \ ((devfsadm_remove_t *)(tbl)) } +#define DEVFSADM_REMOVE_INIT_V1(tbl)\ + _devfsadm_remove_reg_V1_t _devfsadm_remove_reg = {\ + DEVFSADM_V1, \ + (sizeof (tbl) / sizeof (devfsadm_remove_V1_t)), \ + ((devfsadm_remove_V1_t *)(tbl)) } + int devfsadm_noupdate(void); const char *devfsadm_root_path(void); int devfsadm_link_valid(char *link); diff --git a/usr/src/cmd/devfsadm/devfsadm_impl.h b/usr/src/cmd/devfsadm/devfsadm_impl.h index 3c22b42322..5c72e8124f 100644 --- a/usr/src/cmd/devfsadm/devfsadm_impl.h +++ b/usr/src/cmd/devfsadm/devfsadm_impl.h @@ -149,6 +149,7 @@ extern "C" { #define LDEV_DRV_DELIMS ", \t\n" #define LDEV_DEV_DELIM ":" #define LDEV_DRVLIST_NAME "driver" +#define NFP_HASH_SZ 256 #define TYPE_LINK 0x00 #define TYPE_DEVICES 0x01 @@ -284,11 +285,16 @@ struct mlist { }; typedef struct remove_list { - devfsadm_remove_t *remove; + devfsadm_remove_V1_t *remove; module_t *modptr; struct remove_list *next; } remove_list_t; +typedef struct item { + char *i_key; + struct item *i_next; +} item_t; + typedef struct cleanup_data { int flags; char *phypath; @@ -416,7 +422,7 @@ static void recurse_dev_re(char *current_dir, char *path_re, recurse_dev_t *rd); static void matching_dev(char *devpath, void *data); static int resolve_link(char *devpath, char **content_p, int *type_p, char **devfs_path, int dangle); -static int clean_ok(devfsadm_remove_t *remove); +static int clean_ok(devfsadm_remove_V1_t *remove); static int translate_major(dev_t old_dev, dev_t *new_dev); static int get_major_no(char *driver, major_t *major); static int load_n2m_table(char *filename); @@ -511,6 +517,11 @@ static void reset_node_permissions(di_node_t, di_minor_t); static void devname_lookup_handler(void *, char *, size_t, door_desc_t *, uint_t); /* /dev name lookup server */ static int devname_kcall(int, void *); /* syscall into the devname fs */ +static void nfphash_create(void); +static int nfphash_fcn(char *key); +static item_t *nfphash_lookup(char *key); +static void nfphash_insert(char *key); +static void nfphash_destroy(void); /* convenient short hands */ #define vprint devfsadm_print diff --git a/usr/src/cmd/devfsadm/lofi_link.c b/usr/src/cmd/devfsadm/lofi_link.c index c002b91e20..d86089f0bb 100644 --- a/usr/src/cmd/devfsadm/lofi_link.c +++ b/usr/src/cmd/devfsadm/lofi_link.c @@ -2,9 +2,8 @@ * CDDL HEADER START * * The contents of this file are subject to the terms of the - * Common Development and Distribution License, Version 1.0 only - * (the "License"). You may not use this file except in compliance - * with the License. + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. @@ -20,8 +19,8 @@ * CDDL HEADER END */ /* - * Copyright (c) 1998-1999,2001 by Sun Microsystems, Inc. - * All rights reserved. + * Copyright 2006 Sun Microsystems, Inc. All rights reserved. + * Use is subject to license terms. */ #pragma ident "%Z%%M% %I% %E% SMI" @@ -37,6 +36,7 @@ static int lofi(di_minor_t minor, di_node_t node); +static int lofi_rm_all(char *link); /* * devfs create callback register @@ -51,11 +51,22 @@ DEVFSADM_CREATE_INIT_V0(lofi_create_cbt); /* * devfs cleanup register */ -static devfsadm_remove_t lofi_remove_cbt[] = { +static devfsadm_remove_V1_t lofi_remove_cbt[] = { {"pseudo", "^r?lofi/[0-9]+$", RM_ALWAYS | RM_PRE | RM_HOT, - ILEVEL_0, devfsadm_rm_all}, + ILEVEL_0, lofi_rm_all}, }; -DEVFSADM_REMOVE_INIT_V0(lofi_remove_cbt); +DEVFSADM_REMOVE_INIT_V1(lofi_remove_cbt); + +/* + * Wrapper around devfsadm_rm_all() that allows termination of remove + * process + */ +static int +lofi_rm_all(char *link) +{ + devfsadm_rm_all(link); + return (DEVFSADM_TERMINATE); +} /* |
